comparison sat_pubsub/pgsql_storage.py @ 467:d86e0f8a1405

privilege: store roster cache in database: - rosters are now stored on database and restored on startup. This way, presence map can be restored without the need to wait for all contact to send presence again - roster version are checked, if a new version is received, presence map is updated accordingly - roster are not retrieved if presence are received in a too short delay (see ROSTER_TTL), to avoid using too much resources if a client connect/disconnect a lot The current behaviour works around XEP-0356 limitations. An update of the XEP will be needed to get roster pushes and roster version.
author Goffi <goffi@goffi.org>
date Fri, 15 Oct 2021 15:30:18 +0200
parents 0d38c3529972
children d993e8b0fd60
comparison
equal deleted inserted replaced
466:0d38c3529972 467:d86e0f8a1405
49 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 49 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
50 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 50 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
51 51
52 52
53 import copy, logging 53 import copy, logging
54 from datetime import datetime, timezone
54 55
55 from zope.interface import implementer 56 from zope.interface import implementer
56 57
57 from twisted.internet import reactor 58 from twisted.internet import reactor
58 from twisted.internet import defer 59 from twisted.internet import defer
59 from twisted.words.protocols.jabber import jid 60 from twisted.words.protocols.jabber import jid
61 from twisted.words.xish import domish
60 from twisted.python import log 62 from twisted.python import log
61 63
62 from wokkel import generic 64 from wokkel import generic
63 from wokkel.pubsub import Subscription, BadRequest 65 from wokkel.pubsub import Subscription, BadRequest
64 66
475 nodes, 477 nodes,
476 node_accesses, 478 node_accesses,
477 item_accesses)) 479 item_accesses))
478 d.addCallback(self.formatLastItems) 480 d.addCallback(self.formatLastItems)
479 return d 481 return d
482
483 def getRosterCache(self):
484 return self.dbpool.runInteraction(self._getRosterCache)
485
486 def _getRosterCache(self, cursor):
487 cursor.execute(
488 "SELECT roster_id, jid, version, updated, roster::text FROM roster"
489 )
490 return [(r.roster_id, jid.JID(r.jid), r.version, r.updated.timestamp(),
491 parseXml(r.roster)) for r in cursor.fetchall()]
492
493 def setRosterCache(
494 self,
495 jid_: jid.JID,
496 version: str,
497 updated: int,
498 roster: domish.Element
499 ):
500 return self.dbpool.runInteraction(self._setRosterCache, jid_, version, updated, roster)
501
502 def _setRosterCache(self, cursor, jid_, version, updated, roster):
503 cursor.execute(
504 "INSERT INTO roster(jid, version, updated, roster) VALUES (%s, %s, %s, %s) "
505 "ON CONFLICT (jid) DO UPDATE SET version=EXCLUDED.version, "
506 "updated=EXCLUDED.updated, roster=EXCLUDED.roster",
507 (
508 jid_.userhost(),
509 version,
510 datetime.fromtimestamp(updated, tz=timezone.utc),
511 roster.toXml()
512 )
513 )
480 514
481 515
482 @implementer(iidavoll.INode) 516 @implementer(iidavoll.INode)
483 class Node: 517 class Node:
484 518