1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
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;
local driver = {};
function driver:open(store, typ)
local mt = self[typ or "keyval"]
if not mt then
return nil, "unsupported-store";
end
return setmetatable({ store = store, type = typ }, mt);
end
function driver:stores(username) -- luacheck: ignore 212/self
return datamanager.stores(username, host);
end
function driver:purge(user) -- luacheck: ignore 212/self
return datamanager.purge(user, host);
end
local keyval = { };
driver.keyval = { __index = keyval };
function keyval:get(user)
return datamanager.load(user, host, self.store);
end
function keyval:set(user, data)
return datamanager.store(user, host, self.store, data);
end
function keyval:users()
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.key then
items:filter(function (item)
return item.key == query.key;
end);
end
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
function archive:dates(username)
local items, err = datamanager.list_load(username, host, self.store);
if not items then return items, err; end
return array(items):pluck("when"):map(datetime.date):unique();
end
function archive:delete(username, query)
if not query or next(query) == nil then
return datamanager.list_store(username, host, self.store, nil);
end
for k in pairs(query) do
if k ~= "end" then return nil, "unsupported-query-field"; end
end
local items, err = datamanager.list_load(username, host, self.store);
if not items then return items, err; end
items = array(items);
items:filter(function (item)
return item.when > query["end"];
end);
local count = #items;
local ok, err = datamanager.list_store(username, host, self.store, items);
if not ok then return ok, err; end
return count;
end
module:provides("storage", driver);
|