message-db-py 0.3.2__tar.gz → 0.3.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {message_db_py-0.3.2 → message_db_py-0.3.4}/PKG-INFO +2 -2
- {message_db_py-0.3.2 → message_db_py-0.3.4}/pyproject.toml +2 -2
- {message_db_py-0.3.2 → message_db_py-0.3.4}/src/message_db/__init__.py +1 -1
- {message_db_py-0.3.2 → message_db_py-0.3.4}/src/message_db/client.py +78 -72
- {message_db_py-0.3.2 → message_db_py-0.3.4}/src/message_db/connection.py +2 -2
- {message_db_py-0.3.2 → message_db_py-0.3.4}/LICENSE +0 -0
- {message_db_py-0.3.2 → message_db_py-0.3.4}/README.md +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: message-db-py
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: The Python interface to the MessageDB Event Store and Message Store
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
Keywords: message-db,event-sourcing,event-store,messaging,cqrs,command-query-responsibility-segregation,events,streaming,database,postgresql,python,async,microservices,distributed-systems,message-queue,event-driven,real-time
|
|
8
8
|
Author: Subhash Bhushan
|
|
9
9
|
Author-email: subhash.bhushan@gmail.com
|
|
10
|
-
Requires-Python: >=3.11
|
|
10
|
+
Requires-Python: >=3.11
|
|
11
11
|
Classifier: Development Status :: 4 - Beta
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
13
|
Classifier: Intended Audience :: Information Technology
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "message-db-py"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.4"
|
|
4
4
|
description = "The Python interface to the MessageDB Event Store and Message Store"
|
|
5
5
|
authors = ["Subhash Bhushan <subhash.bhushan@gmail.com>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -48,7 +48,7 @@ packages = [
|
|
|
48
48
|
]
|
|
49
49
|
|
|
50
50
|
[tool.poetry.dependencies]
|
|
51
|
-
python = "
|
|
51
|
+
python = ">=3.11"
|
|
52
52
|
psycopg2 = "^2.9.11"
|
|
53
53
|
|
|
54
54
|
[tool.poetry.group.dev.dependencies]
|
|
@@ -144,49 +144,51 @@ class MessageDB:
|
|
|
144
144
|
Returns a list of messages from the stream or category starting from the given position.
|
|
145
145
|
"""
|
|
146
146
|
conn = self.connection_pool.get_connection()
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
147
|
+
try:
|
|
148
|
+
cursor = conn.cursor(cursor_factory=RealDictCursor)
|
|
149
|
+
|
|
150
|
+
if not sql:
|
|
151
|
+
if stream_name == "$all":
|
|
152
|
+
sql = """
|
|
153
|
+
SELECT
|
|
154
|
+
id::varchar,
|
|
155
|
+
stream_name::varchar,
|
|
156
|
+
type::varchar,
|
|
157
|
+
position::bigint,
|
|
158
|
+
global_position::bigint,
|
|
159
|
+
data::varchar,
|
|
160
|
+
metadata::varchar,
|
|
161
|
+
time::timestamp
|
|
162
|
+
FROM
|
|
163
|
+
messages
|
|
164
|
+
WHERE
|
|
165
|
+
global_position > %(position)s
|
|
166
|
+
LIMIT %(batch_size)s
|
|
167
|
+
"""
|
|
168
|
+
elif "-" in stream_name:
|
|
169
|
+
sql = "SELECT * FROM get_stream_messages(%(stream_name)s, %(position)s, %(batch_size)s);"
|
|
170
|
+
else:
|
|
171
|
+
sql = "SELECT * FROM get_category_messages(%(stream_name)s::varchar, %(position)s::bigint, %(batch_size)s::bigint"
|
|
172
|
+
if consumer_group_member is not None:
|
|
173
|
+
sql += ", NULL, %(consumer_group_member)s::bigint, %(consumer_group_size)s::bigint"
|
|
174
|
+
sql += ");"
|
|
175
|
+
|
|
176
|
+
params = {
|
|
177
|
+
"stream_name": stream_name,
|
|
178
|
+
"position": position,
|
|
179
|
+
"batch_size": no_of_messages,
|
|
180
|
+
}
|
|
181
|
+
if consumer_group_member is not None:
|
|
182
|
+
params["consumer_group_member"] = consumer_group_member
|
|
183
|
+
params["consumer_group_size"] = consumer_group_size
|
|
184
|
+
|
|
185
|
+
cursor.execute(sql, params)
|
|
186
|
+
raw_messages = cursor.fetchall()
|
|
187
|
+
|
|
188
|
+
conn.commit()
|
|
189
|
+
cursor.close()
|
|
190
|
+
finally:
|
|
191
|
+
self.connection_pool.release(conn)
|
|
190
192
|
|
|
191
193
|
messages = []
|
|
192
194
|
for message in raw_messages:
|
|
@@ -304,45 +306,49 @@ class MessageDB:
|
|
|
304
306
|
raise ValueError(f"{category_name} is not a category")
|
|
305
307
|
|
|
306
308
|
conn = self.connection_pool.get_connection()
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
cursor.execute(
|
|
310
|
-
"""
|
|
311
|
-
SELECT DISTINCT
|
|
312
|
-
substring(stream_name from position('-' in stream_name) + 1)
|
|
313
|
-
FROM message_store.messages
|
|
314
|
-
WHERE stream_name LIKE %(pattern)s
|
|
315
|
-
AND stream_name NOT LIKE %(snapshot_pattern)s
|
|
316
|
-
ORDER BY 1
|
|
317
|
-
""",
|
|
318
|
-
{
|
|
319
|
-
"pattern": f"{category_name}-%",
|
|
320
|
-
"snapshot_pattern": f"{category_name}:snapshot-%",
|
|
321
|
-
},
|
|
322
|
-
)
|
|
323
|
-
identifiers = [row[0] for row in cursor.fetchall() if row[0]]
|
|
309
|
+
try:
|
|
310
|
+
cursor = conn.cursor()
|
|
324
311
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
312
|
+
cursor.execute(
|
|
313
|
+
"""
|
|
314
|
+
SELECT DISTINCT
|
|
315
|
+
substring(stream_name from position('-' in stream_name) + 1)
|
|
316
|
+
FROM message_store.messages
|
|
317
|
+
WHERE stream_name LIKE %(pattern)s
|
|
318
|
+
AND stream_name NOT LIKE %(snapshot_pattern)s
|
|
319
|
+
ORDER BY 1
|
|
320
|
+
""",
|
|
321
|
+
{
|
|
322
|
+
"pattern": f"{category_name}-%",
|
|
323
|
+
"snapshot_pattern": f"{category_name}:snapshot-%",
|
|
324
|
+
},
|
|
325
|
+
)
|
|
326
|
+
identifiers = [row[0] for row in cursor.fetchall() if row[0]]
|
|
327
|
+
|
|
328
|
+
conn.commit()
|
|
329
|
+
cursor.close()
|
|
330
|
+
finally:
|
|
331
|
+
self.connection_pool.release(conn)
|
|
328
332
|
|
|
329
333
|
return identifiers
|
|
330
334
|
|
|
331
335
|
def read_last_message(self, stream_name: str) -> Dict[str, Any] | None:
|
|
332
336
|
"""Read the last message from a stream."""
|
|
333
337
|
conn = self.connection_pool.get_connection()
|
|
334
|
-
|
|
338
|
+
try:
|
|
339
|
+
cursor = conn.cursor(cursor_factory=RealDictCursor)
|
|
335
340
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
341
|
+
cursor.execute(
|
|
342
|
+
"SELECT * from get_last_stream_message(%(stream_name)s);",
|
|
343
|
+
{"stream_name": stream_name},
|
|
344
|
+
)
|
|
340
345
|
|
|
341
|
-
|
|
346
|
+
message = cursor.fetchone()
|
|
342
347
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
348
|
+
conn.commit()
|
|
349
|
+
cursor.close()
|
|
350
|
+
finally:
|
|
351
|
+
self.connection_pool.release(conn)
|
|
346
352
|
|
|
347
353
|
if message:
|
|
348
354
|
message["data"] = json.loads(message["data"])
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
from typing import Any
|
|
4
4
|
|
|
5
5
|
from psycopg2.extensions import connection
|
|
6
|
-
from psycopg2.pool import
|
|
6
|
+
from psycopg2.pool import ThreadedConnectionPool
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class ConnectionPool:
|
|
@@ -35,7 +35,7 @@ class ConnectionPool:
|
|
|
35
35
|
# Minimum connections start at 1
|
|
36
36
|
min_connections = 1
|
|
37
37
|
|
|
38
|
-
self._connection_pool =
|
|
38
|
+
self._connection_pool = ThreadedConnectionPool(
|
|
39
39
|
min_connections, self.max_connections, *self.args, **self.kwargs
|
|
40
40
|
)
|
|
41
41
|
|
|
File without changes
|
|
File without changes
|