Software /
code /
prosody
Comparison
plugins/mod_storage_sql.lua @ 9883:f76bd399267c
mod_storage_internal,_sql: Add limit to number of items in an archive store (fixes #733)
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Fri, 20 Oct 2017 12:53:53 +0200 |
parent | 9691:e11e076f0eb8 |
child | 9884:9751c17f5281 |
comparison
equal
deleted
inserted
replaced
9882:18f025b3987d | 9883:f76bd399267c |
---|---|
1 | 1 |
2 -- luacheck: ignore 212/self | 2 -- luacheck: ignore 212/self |
3 | 3 |
4 local cache = require "util.cache"; | |
4 local json = require "util.json"; | 5 local json = require "util.json"; |
5 local sql = require "util.sql"; | 6 local sql = require "util.sql"; |
6 local xml_parse = require "util.xml".parse; | 7 local xml_parse = require "util.xml".parse; |
7 local uuid = require "util.uuid"; | 8 local uuid = require "util.uuid"; |
8 local resolve_relative_path = require "util.paths".resolve_relative_path; | 9 local resolve_relative_path = require "util.paths".resolve_relative_path; |
146 return iterator(result); | 147 return iterator(result); |
147 end | 148 end |
148 | 149 |
149 --- Archive store API | 150 --- Archive store API |
150 | 151 |
152 local archive_item_limit = module:get_option_number("storage_archive_item_limit", 1000); | |
153 local archive_item_count_cache = cache.new(module:get_option("storage_archive_item_limit_cache_size", 1000)); | |
154 | |
151 -- luacheck: ignore 512 431/user 431/store | 155 -- luacheck: ignore 512 431/user 431/store |
152 local map_store = {}; | 156 local map_store = {}; |
153 map_store.__index = map_store; | 157 map_store.__index = map_store; |
154 map_store.remove = {}; | 158 map_store.remove = {}; |
155 function map_store:get(username, key) | 159 function map_store:get(username, key) |
229 archive_store.caps = { | 233 archive_store.caps = { |
230 total = true; | 234 total = true; |
231 }; | 235 }; |
232 archive_store.__index = archive_store | 236 archive_store.__index = archive_store |
233 function archive_store:append(username, key, value, when, with) | 237 function archive_store:append(username, key, value, when, with) |
238 local item_count = archive_item_count_cache:get(username); | |
239 if not item_count then | |
240 local ok, ret = engine:transaction(function() | |
241 local count_sql = [[ | |
242 SELECT COUNT(*) FROM "prosodyarchive" | |
243 WHERE "host"=? AND "user"=? AND "store"=?; | |
244 ]]; | |
245 local result = engine:select(count_sql, host, user, store); | |
246 if result then | |
247 for row in result do | |
248 item_count = row[1]; | |
249 end | |
250 end | |
251 end); | |
252 if not ok or not item_count then | |
253 module:log("error", "Failed while checking quota for %s: %s", username, ret); | |
254 return nil, "Failure while checking quota"; | |
255 end | |
256 archive_item_count_cache:set(username, item_count); | |
257 end | |
258 | |
259 module:log("debug", "%s has %d items out of %d limit", username, item_count, archive_item_limit); | |
260 if item_count >= archive_item_limit then | |
261 return nil, "quota-limit"; | |
262 end | |
263 | |
234 local user,store = username,self.store; | 264 local user,store = username,self.store; |
235 when = when or os.time(); | 265 when = when or os.time(); |
236 with = with or ""; | 266 with = with or ""; |
237 local ok, ret = engine:transaction(function() | 267 local ok, ret = engine:transaction(function() |
238 local delete_sql = [[ | 268 local delete_sql = [[ |
243 INSERT INTO "prosodyarchive" | 273 INSERT INTO "prosodyarchive" |
244 ("host", "user", "store", "when", "with", "key", "type", "value") | 274 ("host", "user", "store", "when", "with", "key", "type", "value") |
245 VALUES (?,?,?,?,?,?,?,?); | 275 VALUES (?,?,?,?,?,?,?,?); |
246 ]]; | 276 ]]; |
247 if key then | 277 if key then |
248 engine:delete(delete_sql, host, user or "", store, key); | 278 local result, err = engine:delete(delete_sql, host, user or "", store, key); |
279 if result then | |
280 item_count = item_count - result:affected(); | |
281 archive_item_count_cache:set(username, item_count); | |
282 end | |
249 else | 283 else |
284 item_count = item_count + 1; | |
250 key = uuid.generate(); | 285 key = uuid.generate(); |
251 end | 286 end |
252 local t, encoded_value = assert(serialize(value)); | 287 local t, encoded_value = assert(serialize(value)); |
253 engine:insert(insert_sql, host, user or "", store, when, with, key, t, encoded_value); | 288 engine:insert(insert_sql, host, user or "", store, when, with, key, t, encoded_value); |
289 archive_item_count_cache:set(username, item_count+1); | |
254 return key; | 290 return key; |
255 end); | 291 end); |
256 if not ok then return ok, ret; end | 292 if not ok then return ok, ret; end |
257 return ret; -- the key | 293 return ret; -- the key |
258 end | 294 end |
420 sql_query = string.format(sql_query, t_concat(where, " AND "), | 456 sql_query = string.format(sql_query, t_concat(where, " AND "), |
421 query.reverse and "ASC" or "DESC", unlimited); | 457 query.reverse and "ASC" or "DESC", unlimited); |
422 end | 458 end |
423 return engine:delete(sql_query, unpack(args)); | 459 return engine:delete(sql_query, unpack(args)); |
424 end); | 460 end); |
461 archive_item_count_cache:set(username, nil); | |
425 return ok and stmt:affected(), stmt; | 462 return ok and stmt:affected(), stmt; |
426 end | 463 end |
427 | 464 |
428 local stores = { | 465 local stores = { |
429 keyval = keyval_store; | 466 keyval = keyval_store; |