view mod_mam/fallback_archive.lib.lua @ 2494:d300ae5dba87

mod_smacks: Fix some bugs with smacks-ack-delayed event triggering. The old code had several flaws which are addressed here. First of all this fixes the if statement guarding the event generation There where some timing glitches addressed by this commit as well.
author tmolitor <thilo@eightysoft.de>
date Sun, 12 Feb 2017 21:23:22 +0100
parents 98b4794b72e4
children 03f6d9ed2903
line wrap: on
line source

-- 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;