mod_storage_internal: Add basic archive store implementation
authorKim Alvefur <zash@zash.se>
Fri, 31 Mar 2017 17:47:06 +0200
changeset 8024 83f18982bcfd
parent 8023 342ce07836de
child 8025 05e201468f27
mod_storage_internal: Add basic archive store implementation
plugins/mod_storage_internal.lua
--- a/plugins/mod_storage_internal.lua	Fri Mar 31 17:39:41 2017 +0200
+++ b/plugins/mod_storage_internal.lua	Fri Mar 31 17:47:06 2017 +0200
@@ -1,4 +1,9 @@
 local datamanager = require "core.storagemanager".olddm;
+local array = require "util.array";
+local datetime = require "util.datetime";
+local st = require "util.stanza";
+local now = require "util.time".now;
+local id = require "util.id".medium;
 
 local host = module.host;
 
@@ -35,4 +40,84 @@
 	return datamanager.users(host, self.store, self.type);
 end
 
+local archive = {};
+driver.archive = { __index = archive };
+
+function archive:append(username, key, value, when, with)
+	key = key or id();
+	when = when or now();
+	if not st.is_stanza(value) then
+		return nil, "unsupported-datatype";
+	end
+	value = st.preserialize(st.clone(value));
+	value.key = key;
+	value.when = when;
+	value.with = with;
+	value.attr.stamp = datetime.datetime(when);
+	value.attr.stamp_legacy = datetime.legacy(when);
+	local ok, err = datamanager.list_append(username, host, self.store, value);
+	if not ok then return ok, err; end
+	return key;
+end
+
+function archive:find(username, query)
+	local items, err = datamanager.list_load(username, host, self.store);
+	if not items then return items, err; end
+	local count = #items;
+	local i = 0;
+	if query then
+		items = array(items);
+		if query.with then
+			items:filter(function (item)
+				return item.with == query.with;
+			end);
+		end
+		if query.start then
+			items:filter(function (item)
+				return item.when >= query.start;
+			end);
+		end
+		if query["end"] then
+			items:filter(function (item)
+				return item.when <= query["end"];
+			end);
+		end
+		count = #items;
+		if query.reverse then
+			items:reverse();
+			if query.before then
+				for j = 1, count do
+					if (items[j].key or tostring(j)) == query.before then
+						i = j;
+						break;
+					end
+				end
+			end
+		elseif query.after then
+			for j = 1, count do
+				if (items[j].key or tostring(j)) == query.after then
+					i = j;
+					break;
+				end
+			end
+		end
+		if query.limit and #items - i > query.limit then
+			items[i+query.limit+1] = nil;
+		end
+	end
+	return function ()
+		i = i + 1;
+		local item = items[i];
+		if not item then return; end
+		local key = item.key or tostring(i);
+		local when = item.when or datetime.parse(item.attr.stamp);
+		local with = item.with;
+		item.key, item.when, item.with = nil, nil, nil;
+		item.attr.stamp = nil;
+		item.attr.stamp_legacy = nil;
+		item = st.deserialize(item);
+		return key, item, when, with;
+	end, count;
+end
+
 module:provides("storage", driver);