diff options
-rw-r--r-- | plugins/mod_storage_memory.lua | 82 | ||||
-rw-r--r-- | spec/scansion/pubsub_multi_items.scs | 202 |
2 files changed, 253 insertions, 31 deletions
diff --git a/plugins/mod_storage_memory.lua b/plugins/mod_storage_memory.lua index 3a9de1cc..5a6ce6bf 100644 --- a/plugins/mod_storage_memory.lua +++ b/plugins/mod_storage_memory.lua @@ -76,47 +76,67 @@ function archive_store:append(username, key, value, when, with) return key; end -local function archive_iter (a, start, stop, step, limit, when_start, when_end, match_with) - local item, when, with; - local count = 0; - coroutine.yield(true); -- Ready - for i = start, stop, step do - item = a[i]; - when, with = item.when, item.with; - if when >= when_start and when_end >= when and (not match_with or match_with == with) then - coroutine.yield(item.key, item.value(), when, with); - count = count + 1; - if limit and count >= limit then return end - end - end -end - function archive_store:find(username, query) - local a = self.store[username or NULL] or {}; - local start, stop, step = 1, #a, 1; - local qstart, qend, qwith = -math.huge, math.huge; - local limit; + local items = self.store[username or NULL]; + if not items then + return function () end, 0; + end + local count = #items; + local i = 0; if query then - module:log("debug", "query included") + items = array():append(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 - start, stop, step = stop, start, -1; + items:reverse(); if query.before then - start = a[query.before]; + 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 - start = a[query.after]; + 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 - limit = query.limit; - qstart = query.start or qstart; - qend = query["end"] or qend; - qwith = query.with; end - if not start then return nil, "invalid-key"; end - local iter = coroutine.wrap(archive_iter); - iter(a, start, stop, step, limit, qstart, qend, qwith); - return iter; + return function () + i = i + 1; + local item = items[i]; + if not item then return; end + return item.key, item.value(), item.when, item.with; + end, count; end + function archive_store:delete(username, query) if not query or next(query) == nil then self.store[username or NULL] = nil; diff --git a/spec/scansion/pubsub_multi_items.scs b/spec/scansion/pubsub_multi_items.scs new file mode 100644 index 00000000..147aaa8d --- /dev/null +++ b/spec/scansion/pubsub_multi_items.scs @@ -0,0 +1,202 @@ +# Pubsub: Requesting multiple specific items from a node (#1322) + +[Client] Alice + jid: admin@localhost + password: password + +--------- + +Alice connects + +Alice sends: + <presence xmlns:stream="http://etherx.jabber.org/streams" id=":7IoqYcT3191rfk_dZGo2"/> + +Alice receives: + <presence xmlns:stream="http://etherx.jabber.org/streams" from="${Alice's full JID}" id=":7IoqYcT3191rfk_dZGo2"/> + +Alice sends: + <iq xmlns:stream="http://etherx.jabber.org/streams" to="pubsub.localhost" id=":m0SM8Hn5JxP9BJJ_X4Mz" type="set"> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <create node="e96caf12-264f-4e5a-988e-00ae191771b6"/> + </pubsub> + </iq> + +Alice receives: + <iq xmlns:stream="http://etherx.jabber.org/streams" to="${Alice's full JID}" from="pubsub.localhost" type="result" id=":m0SM8Hn5JxP9BJJ_X4Mz"/> + +Alice sends: + <iq xmlns:stream="http://etherx.jabber.org/streams" to="pubsub.localhost" id=":gwZgEQmzAHcQz-FZOxi-" type="get"> + <pubsub xmlns="http://jabber.org/protocol/pubsub#owner"> + <configure node="e96caf12-264f-4e5a-988e-00ae191771b6"/> + </pubsub> + </iq> + +Alice receives: + <iq xmlns:stream="http://etherx.jabber.org/streams" to="${Alice's full JID}" from="pubsub.localhost" type="result" id=":gwZgEQmzAHcQz-FZOxi-"> + <pubsub xmlns="http://jabber.org/protocol/pubsub#owner"> + <configure node="e96caf12-264f-4e5a-988e-00ae191771b6"> + <x xmlns="jabber:x:data" type="form"> + <field var="FORM_TYPE" type="hidden"> + <value>http://jabber.org/protocol/pubsub#node_config</value> + </field> + <field var="pubsub#title" label="Title" type="text-single"/> + <field var="pubsub#description" label="Description" type="text-single"/> + <field var="pubsub#type" label="The type of node data, usually specified by the namespace of the payload (if any)" type="text-single"/> + <field var="pubsub#max_items" label="Max # of items to persist" type="text-single"> + <validate xmlns="http://jabber.org/protocol/xdata-validate" datatype="xs:integer"/> + <value>20</value> + </field> + <field var="pubsub#persist_items" label="Persist items to storage" type="boolean"> + <value>0</value> + </field> + <field var="pubsub#access_model" label="Specify the subscriber model" type="list-single"> + <option label="authorize"> + <value>authorize</value> + </option> + <option label="open"> + <value>open</value> + </option> + <option label="presence"> + <value>presence</value> + </option> + <option label="roster"> + <value>roster</value> + </option> + <option label="whitelist"> + <value>whitelist</value> + </option> + <value>open</value> + </field> + <field var="pubsub#publish_model" label="Specify the publisher model" type="list-single"> + <option label="publishers"> + <value>publishers</value> + </option> + <option label="subscribers"> + <value>subscribers</value> + </option> + <option label="open"> + <value>open</value> + </option> + <value>publishers</value> + </field> + <field var="pubsub#deliver_notifications" label="Whether to deliver event notifications" type="boolean"> + <value>1</value> + </field> + <field var="pubsub#deliver_payloads" label="Whether to deliver payloads with event notifications" type="boolean"> + <value>1</value> + </field> + <field var="pubsub#notification_type" label="Specify the delivery style for notifications" type="list-single"> + <option label="Messages of type normal"> + <value>normal</value> + </option> + <option label="Messages of type headline"> + <value>headline</value> + </option> + <value>headline</value> + </field> + <field var="pubsub#notify_delete" label="Whether to notify subscribers when the node is deleted" type="boolean"> + <value>1</value> + </field> + <field var="pubsub#notify_retract" label="Whether to notify subscribers when items are removed from the node" type="boolean"> + <value>1</value> + </field> + </x> + </configure> + </pubsub> + </iq> + +Alice sends: + <iq xmlns:stream="http://etherx.jabber.org/streams" to="pubsub.localhost" id=":pfWBQ2MNIq8ieul57Qp7" type="set"> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <publish node="e96caf12-264f-4e5a-988e-00ae191771b6"> + <item id="20e9eb9e-8acb-436e-a486-40e80400faf1"> + <foo xmlns="https://zombofant.net/xmlns/aioxmpp#test">foo</foo> + </item> + </publish> + </pubsub> + </iq> + +Alice receives: + <iq xmlns:stream="http://etherx.jabber.org/streams" to="${Alice's full JID}" from="pubsub.localhost" type="result" id=":pfWBQ2MNIq8ieul57Qp7"> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <publish node="e96caf12-264f-4e5a-988e-00ae191771b6"> + <item id="20e9eb9e-8acb-436e-a486-40e80400faf1"/> + </publish> + </pubsub> + </iq> + +Alice sends: + <iq xmlns:stream="http://etherx.jabber.org/streams" to="pubsub.localhost" id=":Q5TLT6nsW0HHdkDgrPPe" type="set"> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <publish node="e96caf12-264f-4e5a-988e-00ae191771b6"> + <item id="4b94623d-1127-41c0-ac47-e283fd890557"> + <foo xmlns="https://zombofant.net/xmlns/aioxmpp#test">bar</foo> + </item> + </publish> + </pubsub> + </iq> + +Alice receives: + <iq xmlns:stream="http://etherx.jabber.org/streams" to="${Alice's full JID}" from="pubsub.localhost" type="result" id=":Q5TLT6nsW0HHdkDgrPPe"> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <publish node="e96caf12-264f-4e5a-988e-00ae191771b6"> + <item id="4b94623d-1127-41c0-ac47-e283fd890557"/> + </publish> + </pubsub> + </iq> + +Alice sends: + <iq xmlns:stream="http://etherx.jabber.org/streams" to="pubsub.localhost" id=":3nvB2E20p1iuM6lOPaP6" type="get"> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <items node="e96caf12-264f-4e5a-988e-00ae191771b6"> + <item id="20e9eb9e-8acb-436e-a486-40e80400faf1"/> + <item id="4b94623d-1127-41c0-ac47-e283fd890557"/> + </items> + </pubsub> + </iq> + +Alice receives: + <iq xmlns:stream="http://etherx.jabber.org/streams" to="${Alice's full JID}" from="pubsub.localhost" type="result" id=":3nvB2E20p1iuM6lOPaP6"> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <items node="e96caf12-264f-4e5a-988e-00ae191771b6"> + <item xmlns="http://jabber.org/protocol/pubsub" id="20e9eb9e-8acb-436e-a486-40e80400faf1"> + <foo xmlns="https://zombofant.net/xmlns/aioxmpp#test">foo</foo> + </item> + <item xmlns="http://jabber.org/protocol/pubsub" id="4b94623d-1127-41c0-ac47-e283fd890557"> + <foo xmlns="https://zombofant.net/xmlns/aioxmpp#test">bar</foo> + </item> + </items> + </pubsub> + </iq> + +Alice sends: + <iq xmlns:stream="http://etherx.jabber.org/streams" to="pubsub.localhost" id=":XQdyK54iyOKiJvUoX9t_" type="get"> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <items node="e96caf12-264f-4e5a-988e-00ae191771b6"/> + </pubsub> + </iq> + +Alice receives: + <iq xmlns:stream="http://etherx.jabber.org/streams" to="${Alice's full JID}" from="pubsub.localhost" type="result" id=":XQdyK54iyOKiJvUoX9t_"> + <pubsub xmlns="http://jabber.org/protocol/pubsub"> + <items node="e96caf12-264f-4e5a-988e-00ae191771b6"> + <item xmlns="http://jabber.org/protocol/pubsub" id="20e9eb9e-8acb-436e-a486-40e80400faf1"> + <foo xmlns="https://zombofant.net/xmlns/aioxmpp#test">foo</foo> + </item> + <item xmlns="http://jabber.org/protocol/pubsub" id="4b94623d-1127-41c0-ac47-e283fd890557"> + <foo xmlns="https://zombofant.net/xmlns/aioxmpp#test">bar</foo> + </item> + </items> + </pubsub> + </iq> + +Alice sends: + <iq xmlns:stream="http://etherx.jabber.org/streams" to="pubsub.localhost" id=":ySGQOz5tnyWT82idwJZP" type="set"> + <pubsub xmlns="http://jabber.org/protocol/pubsub#owner"> + <delete node="e96caf12-264f-4e5a-988e-00ae191771b6"/> + </pubsub> + </iq> + +Alice receives: + <iq xmlns:stream="http://etherx.jabber.org/streams" to="${Alice's full JID}" from="pubsub.localhost" type="result" id=":ySGQOz5tnyWT82idwJZP"/> + |