Comparison

util/pubsub.lua @ 5972:f365d3c8fd2c

util.pubsub: Separate data from node configuration
author Kim Alvefur <zash@zash.se>
date Mon, 30 Dec 2013 23:49:23 +0100
parent 5971:637731f0b9a3
child 5973:905b4fd863b4
child 6435:689cb04ff9fd
comparison
equal deleted inserted replaced
5971:637731f0b9a3 5972:f365d3c8fd2c
1 local events = require "util.events"; 1 local events = require "util.events";
2 local t_remove = table.remove;
2 3
3 module("pubsub", package.seeall); 4 module("pubsub", package.seeall);
4 5
5 local service = {}; 6 local service = {};
6 local service_mt = { __index = service }; 7 local service_mt = { __index = service };
16 return setmetatable({ 17 return setmetatable({
17 config = setmetatable(config, { __index = default_config }); 18 config = setmetatable(config, { __index = default_config });
18 affiliations = {}; 19 affiliations = {};
19 subscriptions = {}; 20 subscriptions = {};
20 nodes = {}; 21 nodes = {};
22 data = {};
21 events = events.new(); 23 events = events.new();
22 }, service_mt); 24 }, service_mt);
23 end 25 end
24 26
25 function service:jids_equal(jid1, jid2) 27 function service:jids_equal(jid1, jid2)
210 -- 212 --
211 if self.nodes[node] then 213 if self.nodes[node] then
212 return false, "conflict"; 214 return false, "conflict";
213 end 215 end
214 216
217 self.data[node] = {};
215 self.nodes[node] = { 218 self.nodes[node] = {
216 name = node; 219 name = node;
217 subscribers = {}; 220 subscribers = {};
218 config = {}; 221 config = {};
219 data = {};
220 affiliations = {}; 222 affiliations = {};
221 }; 223 };
224 setmetatable(self.nodes[node], { __index = { data = self.data[node] } }); -- COMPAT
222 self.events.fire_event("node-created", { node = node, actor = actor }); 225 self.events.fire_event("node-created", { node = node, actor = actor });
223 local ok, err = self:set_affiliation(node, true, actor, "owner"); 226 local ok, err = self:set_affiliation(node, true, actor, "owner");
224 if not ok then 227 if not ok then
225 self.nodes[node] = nil; 228 self.nodes[node] = nil;
229 self.data[node] = nil;
226 end 230 end
227 return ok, err; 231 return ok, err;
228 end 232 end
229 233
230 function service:delete(node, actor) 234 function service:delete(node, actor)
236 local node_obj = self.nodes[node]; 240 local node_obj = self.nodes[node];
237 if not node_obj then 241 if not node_obj then
238 return false, "item-not-found"; 242 return false, "item-not-found";
239 end 243 end
240 self.nodes[node] = nil; 244 self.nodes[node] = nil;
245 self.data[node] = nil;
241 self.events.fire_event("node-deleted", { node = node, actor = actor }); 246 self.events.fire_event("node-deleted", { node = node, actor = actor });
242 self.config.broadcaster("delete", node, node_obj.subscribers); 247 self.config.broadcaster("delete", node, node_obj.subscribers);
243 return true; 248 return true;
249 end
250
251 local function remove_item_by_id(data, id)
252 if not data[id] then return end
253 data[id] = nil;
254 for i, _id in ipairs(data) do
255 if id == _id then
256 t_remove(data, i);
257 return i;
258 end
259 end
244 end 260 end
245 261
246 function service:publish(node, actor, id, item) 262 function service:publish(node, actor, id, item)
247 -- Access checking 263 -- Access checking
248 if not self:may(node, actor, "publish") then 264 if not self:may(node, actor, "publish") then
258 if not ok then 274 if not ok then
259 return ok, err; 275 return ok, err;
260 end 276 end
261 node_obj = self.nodes[node]; 277 node_obj = self.nodes[node];
262 end 278 end
263 node_obj.data[id] = item; 279 local node_data = self.data[node];
280 remove_item_by_id(node_data, id);
281 node_data[#self.data[node] + 1] = id;
282 node_data[id] = item;
264 self.events.fire_event("item-published", { node = node, actor = actor, id = id, item = item }); 283 self.events.fire_event("item-published", { node = node, actor = actor, id = id, item = item });
265 self.config.broadcaster("items", node, node_obj.subscribers, item); 284 self.config.broadcaster("items", node, node_obj.subscribers, item);
266 return true; 285 return true;
267 end 286 end
268 287
271 if not self:may(node, actor, "retract") then 290 if not self:may(node, actor, "retract") then
272 return false, "forbidden"; 291 return false, "forbidden";
273 end 292 end
274 -- 293 --
275 local node_obj = self.nodes[node]; 294 local node_obj = self.nodes[node];
276 if (not node_obj) or (not node_obj.data[id]) then 295 if (not node_obj) or (not self.data[node][id]) then
277 return false, "item-not-found"; 296 return false, "item-not-found";
278 end 297 end
279 self.events.fire_event("item-retracted", { node = node, actor = actor, id = id }); 298 self.events.fire_event("item-retracted", { node = node, actor = actor, id = id });
280 node_obj.data[id] = nil; 299 remove_item_by_id(self.data[node], id);
281 if retract then 300 if retract then
282 self.config.broadcaster("items", node, node_obj.subscribers, retract); 301 self.config.broadcaster("items", node, node_obj.subscribers, retract);
283 end 302 end
284 return true 303 return true
285 end 304 end
292 -- 311 --
293 local node_obj = self.nodes[node]; 312 local node_obj = self.nodes[node];
294 if not node_obj then 313 if not node_obj then
295 return false, "item-not-found"; 314 return false, "item-not-found";
296 end 315 end
297 node_obj.data = {}; -- Purge 316 self.data[node] = {}; -- Purge
298 self.events.fire_event("node-purged", { node = node, actor = actor }); 317 self.events.fire_event("node-purged", { node = node, actor = actor });
299 if notify then 318 if notify then
300 self.config.broadcaster("purge", node, node_obj.subscribers); 319 self.config.broadcaster("purge", node, node_obj.subscribers);
301 end 320 end
302 return true 321 return true
311 local node_obj = self.nodes[node]; 330 local node_obj = self.nodes[node];
312 if not node_obj then 331 if not node_obj then
313 return false, "item-not-found"; 332 return false, "item-not-found";
314 end 333 end
315 if id then -- Restrict results to a single specific item 334 if id then -- Restrict results to a single specific item
316 return true, { [id] = node_obj.data[id] }; 335 return true, { id, [id] = self.data[node][id] };
317 else 336 else
318 return true, node_obj.data; 337 return true, self.data[node];
319 end 338 end
320 end 339 end
321 340
322 function service:get_nodes(actor) 341 function service:get_nodes(actor)
323 -- Access checking 342 -- Access checking