Diff

mod_mam/fallback_archive.lib.lua @ 2023:98b4794b72e4

mod_mam: Include an in-memory fallback driver
author Kim Alvefur <zash@zash.se>
date Tue, 19 Jan 2016 17:47:47 +0100
child 2508:03f6d9ed2903
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_mam/fallback_archive.lib.lua	Tue Jan 19 17:47:47 2016 +0100
@@ -0,0 +1,84 @@
+-- luacheck: ignore 212/self
+
+local uuid = require "util.uuid".generate;
+local store = module:shared("archive");
+local archive_store = { _provided_by = "mam"; name = "fallback"; };
+
+function archive_store:append(username, key, value, when, with)
+	local archive = store[username];
+	if not archive then
+		archive = { [0] = 0 };
+		store[username] = archive;
+	end
+	local index = (archive[0] or #archive)+1;
+	local item = { key = key, when = when, with = with, value = value };
+	if not key or archive[key] then
+		key = uuid();
+		item.key = key;
+	end
+	archive[index] = item;
+	archive[key] = index;
+	archive[0] = index;
+	return key;
+end
+
+function archive_store:find(username, query)
+	local archive = store[username] or {};
+	local start, stop, step = 1, archive[0] or #archive, 1;
+	local qstart, qend, qwith = -math.huge, math.huge;
+	local limit;
+
+	if query then
+		if query.reverse then
+			start, stop, step = stop, start, -1;
+			if query.before and archive[query.before] then
+				start = archive[query.before] - 1;
+			end
+		elseif query.after and archive[query.after] then
+			start = archive[query.after] + 1;
+		end
+		qwith = query.with;
+		limit = query.limit;
+		qstart = query.start or qstart;
+		qend = query["end"] or qend;
+	end
+
+	return function ()
+		if limit and limit <= 0 then return end
+		for i = start, stop, step do
+			local item = archive[i];
+			if (not qwith or qwith == item.with) and item.when >= qstart and item.when <= qend then
+				if limit then limit = limit - 1; end
+				start = i + step; -- Start on next item
+				return item.key, item.value, item.when, item.with;
+			end
+		end
+	end
+end
+
+function archive_store:delete(username, query)
+	if not query or next(query) == nil then
+		-- no specifics, delete everything
+		store[username] = nil;
+		return true;
+	end
+	local archive = store[username];
+	if not archive then return true; end -- no messages, nothing to delete
+
+	local start, stop, step = 1, archive[0] or #archive, 1;
+	local qstart = query.start or -math.huge;
+	local qend = query["end"] or math.huge;
+	local qwith = query.with;
+	store[username] = nil;
+	for i = 1, #archive do
+		local item = archive[i];
+		local when, with = item.when, item.when;
+		-- Add things that don't match the query
+		if not ((not qwith or qwith == item.with) and item.when >= qstart and item.when <= qend) then
+			self:append(username, item.key, item.value, when, with);
+		end
+	end
+	return true;
+end
+
+return archive_store;