Mercurial > prosody-modules
comparison mod_storage_s3/mod_storage_s3.lua @ 5736:ba731ff5b895
mod_storage_s3: Reorder path components (BC: invalidates any existing data)
keyvalue: /bucket/hostname/username/store
archive: /bucket/hostname/username/store/yyyy-mm-dd/with/key
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Mon, 27 Nov 2023 09:30:04 +0100 |
| parents | 9a1d8c39d0b0 |
| children | 72b0fa7e36dc |
comparison
equal
deleted
inserted
replaced
| 5735:9a1d8c39d0b0 | 5736:ba731ff5b895 |
|---|---|
| 153 function keyval:_path(key) | 153 function keyval:_path(key) |
| 154 return url.build_path({ | 154 return url.build_path({ |
| 155 is_absolute = true; | 155 is_absolute = true; |
| 156 bucket; | 156 bucket; |
| 157 jid.escape(module.host); | 157 jid.escape(module.host); |
| 158 jid.escape(key or "@"); | |
| 158 jid.escape(self.store); | 159 jid.escape(self.store); |
| 159 jid.escape(key or "@"); | |
| 160 }) | 160 }) |
| 161 end | 161 end |
| 162 | 162 |
| 163 function keyval:get(user) | 163 function keyval:get(user) |
| 164 return async.wait_for(new_request(self, "GET", self:_path(user)):next(on_result)); | 164 return async.wait_for(new_request(self, "GET", self:_path(user)):next(on_result)); |
| 173 return async.wait_for(new_request(self, "PUT", self:_path(user), nil, data)); | 173 return async.wait_for(new_request(self, "PUT", self:_path(user), nil, data)); |
| 174 end | 174 end |
| 175 | 175 |
| 176 function keyval:users() | 176 function keyval:users() |
| 177 local bucket_path = url.build_path({ is_absolute = true; bucket; is_directory = true }); | 177 local bucket_path = url.build_path({ is_absolute = true; bucket; is_directory = true }); |
| 178 local prefix = url.build_path({ jid.escape(module.host); jid.escape(self.store); is_directory = true }); | 178 local prefix = url.build_path({ jid.escape(module.host); is_directory = true }); |
| 179 local list_result, err = async.wait_for(new_request(self, "GET", bucket_path, { prefix = prefix })) | 179 local list_result, err = async.wait_for(new_request(self, "GET", bucket_path, { prefix = prefix })) |
| 180 if err or list_result.code ~= 200 then | 180 if err or list_result.code ~= 200 then |
| 181 return nil, err; | 181 return nil, err; |
| 182 end | 182 end |
| 183 local list_bucket_result = xml.parse(list_result.body); | 183 local list_bucket_result = xml.parse(list_result.body); |
| 184 if list_bucket_result:get_child_text("IsTruncated") == "true" then | 184 if list_bucket_result:get_child_text("IsTruncated") == "true" then |
| 185 local max_keys = list_bucket_result:get_child_text("MaxKeys"); | 185 local max_keys = list_bucket_result:get_child_text("MaxKeys"); |
| 186 module:log("warn", "Paging truncated results not implemented, max %s %s returned", max_keys, self.store); | 186 module:log("warn", "Paging truncated results not implemented, max %s %s returned", max_keys, self.store); |
| 187 end | 187 end |
| 188 local keys = array(); | 188 local keys = array(); |
| 189 local store_part = jid.escape(self.store); | |
| 189 for content in list_bucket_result:childtags("Contents") do | 190 for content in list_bucket_result:childtags("Contents") do |
| 190 local key = url.parse_path(content:get_child_text("Key")); | 191 local key = url.parse_path(content:get_child_text("Key")); |
| 191 keys:push(jid.unescape(key[3])); | 192 if key[3] == store_part then |
| 193 keys:push(jid.unescape(key[2])); | |
| 194 end | |
| 192 end | 195 end |
| 193 return function() | 196 return function() |
| 194 return keys:pop(); | 197 return keys:pop(); |
| 195 end | 198 end |
| 196 end | 199 end |
| 206 function archive:_path(username, date, when, with, key) | 209 function archive:_path(username, date, when, with, key) |
| 207 return url.build_path({ | 210 return url.build_path({ |
| 208 is_absolute = true; | 211 is_absolute = true; |
| 209 bucket; | 212 bucket; |
| 210 jid.escape(module.host); | 213 jid.escape(module.host); |
| 214 jid.escape(username or "@"); | |
| 211 jid.escape(self.store); | 215 jid.escape(self.store); |
| 212 jid.escape(username or "@"); | 216 date or dt.date(when); |
| 213 jid.escape(with and jid.prep(with) or "@"); | 217 jid.escape(with and jid.prep(with) or "@"); |
| 214 date or dt.date(when); | |
| 215 key; | 218 key; |
| 216 }) | 219 }) |
| 217 end | 220 end |
| 218 | 221 |
| 219 | 222 |
| 233 end)); | 236 end)); |
| 234 end | 237 end |
| 235 | 238 |
| 236 function archive:find(username, query) | 239 function archive:find(username, query) |
| 237 local bucket_path = url.build_path({ is_absolute = true; bucket; is_directory = true }); | 240 local bucket_path = url.build_path({ is_absolute = true; bucket; is_directory = true }); |
| 238 local prefix = { jid.escape(module.host); jid.escape(self.store); is_directory = true }; | 241 local prefix = { jid.escape(module.host); jid.escape(username or "@"); jid.escape(self.store); is_directory = true }; |
| 239 table.insert(prefix, jid.escape(username or "@")); | |
| 240 if not query then | 242 if not query then |
| 241 query = {}; | 243 query = {}; |
| 242 end | 244 end |
| 243 if query["with"] then | 245 |
| 244 table.insert(prefix, jid.escape(jid.prep(query["with"]), true):sub(1,24)); | 246 if query["start"] and query["end"] and dt.date(query["start"]) == dt.date(query["end"]) then |
| 245 if query["start"] and query["end"] and dt.date(query["start"]) == dt.date(query["end"]) then | 247 table.insert(prefix, dt.date(query["start"])); |
| 246 table.insert(prefix, dt.date(query["start"])); | 248 if query["with"] then |
| 249 table.insert(prefix, jid.escape(query["with"])); | |
| 247 end | 250 end |
| 248 end | 251 end |
| 249 | 252 |
| 250 prefix = url.build_path(prefix); | 253 prefix = url.build_path(prefix); |
| 251 local list_result, err = async.wait_for(new_request(self, "GET", bucket_path, { | 254 local list_result, err = async.wait_for(new_request(self, "GET", bucket_path, { |
| 269 iterwrap = it.reverse; | 272 iterwrap = it.reverse; |
| 270 end | 273 end |
| 271 local ids = query["ids"] and set.new(query["ids"]); | 274 local ids = query["ids"] and set.new(query["ids"]); |
| 272 local found = not query["after"]; | 275 local found = not query["after"]; |
| 273 for content in iterwrap(list_bucket_result:childtags("Contents")) do | 276 for content in iterwrap(list_bucket_result:childtags("Contents")) do |
| 274 local key = url.parse_path(content:get_child_text("Key")); | 277 local when, with, id = table.unpack(url.parse_path(content:get_child_text("Key")), 4); |
| 275 if found and query["before"] == key[6] then | 278 with = jid.unescape(with); |
| 279 if found and query["before"] == id then | |
| 276 break | 280 break |
| 277 end | 281 end |
| 278 if (not query["with"] or query["with"] == jid.unescape(key[5])) | 282 if (not query["with"] or query["with"] == with) |
| 279 and (not query["start"] or dt.date(query["start"]) >= key[6]) | 283 and (not query["start"] or dt.date(query["start"]) >= when) |
| 280 and (not query["end"] or dt.date(query["end"]) <= key[6]) | 284 and (not query["end"] or dt.date(query["end"]) <= when) |
| 281 and (not ids or ids:contains(key[6])) | 285 and (not ids or ids:contains(id)) |
| 282 and found then | 286 and found then |
| 283 keys:push({ key = key[6]; date = key[5]; with = jid.unescape(key[4]) }); | 287 keys:push({ key = id; date = when; with = with }); |
| 284 end | 288 end |
| 285 if not found and key[6] == query["after"] then | 289 if not found and id == query["after"] then |
| 286 found = not found | 290 found = not found |
| 287 end | 291 end |
| 288 end | 292 end |
| 289 local i = 0; | 293 local i = 0; |
| 290 local function get_next() | 294 local function get_next() |
