Mercurial > libervia-pubsub
annotate idavoll/pgsql_backend.py @ 51:40ac06941edc
Added node existance checks.
Added Storage support for adding and removing subscriptions.
Added SubscriptionService as subclass of backend.SubscriptionService.
author | Ralph Meijer <ralphm@ik.nu> |
---|---|
date | Wed, 03 Nov 2004 17:27:23 +0000 |
parents | 4447b3c5b857 |
children | 7c4dfef5d964 |
rev | line source |
---|---|
28 | 1 from twisted.application import service |
2 from twisted.internet import defer | |
3 from twisted.protocols.jabber import jid | |
4 from twisted.enterprise import adbapi | |
5 import backend | |
6 | |
41
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
7 class Storage: |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
8 def __init__(self, user, database): |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
9 self.dbpool = adbapi.ConnectionPool('pyPgSQL.PgSQL', user=user, |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
10 database=database) |
28 | 11 |
51 | 12 def _check_node_exists(self, cursor, node_id): |
13 cursor.execute("""SELECT id FROM nodes WHERE node=%s""", | |
14 (node_id.encode('utf8'))) | |
15 if not cursor.fetchone(): | |
16 raise backend.NodeNotFound | |
17 else: | |
18 return | |
19 | |
41
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
20 def _get_node_configuration(self, cursor, node_id): |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
21 configuration = {} |
28 | 22 cursor.execute("""SELECT persistent, deliver_payload FROM nodes |
23 WHERE node=%s""", | |
24 (node_id,)) | |
25 try: | |
41
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
26 (configuration["persist_items"], |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
27 configuration["deliver_payloads"]) = cursor.fetchone() |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
28 return configuration |
28 | 29 except TypeError: |
30 raise backend.NodeNotFound | |
31 | |
41
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
32 def get_node_configuration(self, node_id): |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
33 return self.dbpool.runInteraction(self._get_node_configuration, node_id) |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
34 |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
35 def _get_affiliation(self, cursor, node_id, entity): |
51 | 36 self._check_node_exists(cursor, node_id) |
41
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
37 cursor.execute("""SELECT affiliation FROM affiliations |
28 | 38 JOIN nodes ON (node_id=nodes.id) |
39 JOIN entities ON (entity_id=entities.id) | |
41
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
40 WHERE node=%s AND jid=%s""", |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
41 (node_id.encode('utf8'), entity.encode('utf8'))) |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
42 |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
43 try: |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
44 return cursor.fetchone()[0] |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
45 except TypeError: |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
46 return None |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
47 |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
48 def get_affiliation(self, node_id, entity): |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
49 return self.dbpool.runInteraction(self._get_affiliation, node_id, |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
50 entity) |
28 | 51 |
41
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
52 def get_subscribers(self, node_id): |
51 | 53 self._check_node_exists(cursor, node_id) |
43
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
54 d = self.dbpool.runQuery("""SELECT jid, resource FROM subscriptions |
41
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
55 JOIN nodes ON (node_id=nodes.id) |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
56 JOIN entities ON (entity_id=entities.id) |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
57 WHERE node=%s AND |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
58 subscription='subscribed'""", |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
59 (node_id.encode('utf8'),)) |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
60 d.addCallback(self._convert_to_jids) |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
61 return d |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
62 |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
63 def _convert_to_jids(self, list): |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
64 return [jid.JID("%s/%s" % (l[0], l[1])).full() for l in list] |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
65 |
43
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
66 def store_items(self, node_id, items, publisher): |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
67 return self.dbpool.runInteraction(self._store_items, node_id, items, |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
68 publisher) |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
69 |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
70 def _store_items(self, cursor, node_id, items, publisher): |
51 | 71 self._check_node_exists(cursor, node_id) |
43
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
72 for item in items: |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
73 self._store_item(cursor, node_id, item, publisher) |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
74 |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
75 def _store_item(self, cursor, node_id, item, publisher): |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
76 data = item.toXml() |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
77 cursor.execute("""UPDATE items SET publisher=%s, data=%s |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
78 FROM nodes |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
79 WHERE nodes.id = items.node_id AND |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
80 nodes.node = %s and items.item=%s""", |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
81 (publisher.encode('utf8'), |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
82 data.encode('utf8'), |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
83 node_id.encode('utf8'), |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
84 item["id"].encode('utf8'))) |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
85 if cursor.rowcount == 1: |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
86 return |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
87 |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
88 cursor.execute("""INSERT INTO items (node_id, item, publisher, data) |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
89 SELECT id, %s, %s, %s FROM nodes WHERE node=%s""", |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
90 (item["id"].encode('utf8'), |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
91 publisher.encode('utf8'), |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
92 data.encode('utf8'), |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
93 node_id.encode('utf8'))) |
9685b7e291ef
Moved common stuff out of pgsql_backend.py to backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
41
diff
changeset
|
94 |
51 | 95 def add_subscription(self, node_id, subscriber, state): |
96 return self.dbpool.runInteraction(self._add_subscription, node_id, | |
97 subscriber, state) | |
98 | |
99 def _add_subscription(self, cursor, node_id, subscriber, state): | |
100 self._check_node_exists(cursor, node_id) | |
101 subscriber = jid.JID(subscriber) | |
102 userhost = subscriber.userhost() | |
103 resource = subscriber.resource or '' | |
104 | |
105 try: | |
106 cursor.execute("""INSERT INTO entities (jid) VALUES (%s)""", | |
107 (userhost.encode('utf8'))) | |
108 except: | |
109 pass | |
110 | |
111 try: | |
112 cursor.execute("""INSERT INTO subscriptions | |
113 (node_id, entity_id, resource, subscription) | |
114 SELECT n.id, e.id, %s, %s FROM | |
115 (SELECT id FROM nodes WHERE node=%s) AS n | |
116 CROSS JOIN | |
117 (SELECT id FROM entities WHERE jid=%s) AS e""", | |
118 (resource.encode('utf8'), | |
119 state.encode('utf8'), | |
120 node_id.encode('utf8'), | |
121 userhost.encode('utf8'))) | |
122 except: | |
123 cursor.execute("""SELECT subscription FROM subscriptions | |
124 JOIN nodes ON (nodes.id=subscriptions.node_id) | |
125 JOIN entities ON | |
126 (entities.id=subscriptions.entity_id) | |
127 WHERE node=%s AND jid=%s AND resource=%s""", | |
128 (node_id.encode('utf8'), | |
129 userhost.encode('utf8'), | |
130 resource.encode('utf8'))) | |
131 state = cursor.fetchone()[0] | |
132 | |
133 return {'node': node_id, | |
134 'jid': subscriber.full(), | |
135 'subscription': state} | |
136 | |
137 def remove_subscription(self, node_id, subscriber): | |
138 return self.dbpool.runInteraction(self._remove_subscription, node_id, | |
139 subscriber) | |
140 | |
141 def _remove_subscription(self, cursor, node_id, subscriber): | |
142 self._check_node_exists(cursor, node_id) | |
143 subscriber = jid.JID(subscriber) | |
144 userhost = subscriber.userhost() | |
145 resource = subscriber.resource or '' | |
146 | |
147 cursor.execute("""DELETE FROM subscriptions WHERE | |
148 node_id=(SELECT id FROM nodes WHERE node=%s) AND | |
149 entity_id=(SELECT id FROM entities WHERE jid=%s) | |
150 AND resource=%s""", | |
151 (node_id.encode('utf8'), | |
152 userhost.encode('utf8'), | |
153 resource.encode('utf8'))) | |
154 if cursor.rowcount != 1: | |
155 raise backend.NotSubscribed | |
156 | |
157 return None | |
158 | |
41
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
159 class BackendService(backend.BackendService): |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
160 """ PostgreSQL backend Service for a JEP-0060 pubsub service """ |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
161 |
45
4447b3c5b857
Redefine backend classes as subclass of the implementations in backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
43
diff
changeset
|
162 class PublishService(backend.PublishService): |
4447b3c5b857
Redefine backend classes as subclass of the implementations in backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
43
diff
changeset
|
163 pass |
41
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
164 |
ea3d3544a52e
Rewrite using separated backend interfaces. The backend also uses a separate
Ralph Meijer <ralphm@ik.nu>
parents:
28
diff
changeset
|
165 class NotificationService(backend.NotificationService): |
45
4447b3c5b857
Redefine backend classes as subclass of the implementations in backend.py.
Ralph Meijer <ralphm@ik.nu>
parents:
43
diff
changeset
|
166 pass |
51 | 167 |
168 class SubscriptionService(backend.SubscriptionService): | |
169 pass |