--- a/mod_mam/README.markdown Tue Jan 19 17:47:05 2016 +0100
+++ b/mod_mam/README.markdown Tue Jan 19 17:47:47 2016 +0100
@@ -58,6 +58,9 @@
}
```
+If no archive-capable storage backend can be opened then an in-memory
+one will be used as fallback.
+
Query size limits
-----------------
@@ -116,12 +119,10 @@
------- ---------------
trunk Works
- 0.10 Works [^2]
- 0.9 Unsupported
+ 0.10 Works
+ 0.9 Works
0.8 Does not work
------- ---------------
[^1]: Might be changed to "mam" at some point
-[^2]: requires a storage driver with archive support, eg
- mod\_storage\_sql in 0.10
--- /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;
--- a/mod_mam/mod_mam.lua Tue Jan 19 17:47:05 2016 +0100
+++ b/mod_mam/mod_mam.lua Tue Jan 19 17:47:47 2016 +0100
@@ -39,10 +39,8 @@
local archive = assert(module:open_store(archive_store, "archive"));
if archive.name == "null" then
- module:log("debug", "Attempt to open archive storage returned null driver");
- module:log("error", "Unable to open archive storage, no archive capable storage driver enabled?");
- module:log("info", "See https://prosody.im/doc/storage and https://prosody.im/doc/archiving for more information");
- return;
+ module:log("info", "Using in-memory fallback archive driver");
+ archive = module:require "fallback_archive";
elseif not archive.find then
module:log("debug", "Attempt to open archive storage returned a valid driver but it does not seem to implement the storage API");
module:log("error", "mod_%s does not support archiving", archive._provided_by or archive.name and "storage_"..archive.name.."(?)" or "<unknown>");