dsmq 0.3.0__tar.gz → 0.5.0__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.
@@ -1,3 +1,10 @@
1
+ Metadata-Version: 2.3
2
+ Name: dsmq
3
+ Version: 0.5.0
4
+ Summary: A dead simple message queue
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+
1
8
  # Dead Simple Message Queue
2
9
 
3
10
  ## What it does
@@ -50,6 +57,24 @@ topic = "greetings"
50
57
  msg = mq.get(topic)
51
58
  ```
52
59
 
60
+ ### Spin up and shut down a dsmq in its own process
61
+
62
+ A dsmq server doesn't come with a built-in way to shut itself down.
63
+ It can be helpful to have it running in a separate process that can be
64
+ managed
65
+
66
+ ```python
67
+ import multiprocessing as mp
68
+
69
+ p_mq = mp.Process(target=dsmq.start_server, args=(config.MQ_HOST, config.MQ_PORT))
70
+ p_mq.start()
71
+
72
+ p_mq.join()
73
+ # or
74
+ p_mq.kill()
75
+ p_mq.close()
76
+ ```
77
+
53
78
  ### Demo
54
79
 
55
80
  1. Open 3 separate terminal windows.
@@ -1,11 +1,3 @@
1
- Metadata-Version: 2.3
2
- Name: dsmq
3
- Version: 0.3.0
4
- Summary: A dead simple message queue
5
- License-File: LICENSE
6
- Requires-Python: >=3.10
7
- Description-Content-Type: text/markdown
8
-
9
1
  # Dead Simple Message Queue
10
2
 
11
3
  ## What it does
@@ -58,6 +50,24 @@ topic = "greetings"
58
50
  msg = mq.get(topic)
59
51
  ```
60
52
 
53
+ ### Spin up and shut down a dsmq in its own process
54
+
55
+ A dsmq server doesn't come with a built-in way to shut itself down.
56
+ It can be helpful to have it running in a separate process that can be
57
+ managed
58
+
59
+ ```python
60
+ import multiprocessing as mp
61
+
62
+ p_mq = mp.Process(target=dsmq.start_server, args=(config.MQ_HOST, config.MQ_PORT))
63
+ p_mq.start()
64
+
65
+ p_mq.join()
66
+ # or
67
+ p_mq.kill()
68
+ p_mq.close()
69
+ ```
70
+
61
71
  ### Demo
62
72
 
63
73
  1. Open 3 separate terminal windows.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dsmq"
3
- version = "0.3.0"
3
+ version = "0.5.0"
4
4
  description = "A dead simple message queue"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -10,6 +10,8 @@ DEFAULT_PORT = 30008
10
10
 
11
11
  N_RETRIES = 5
12
12
  FIRST_RETRY = 0.01 # seconds
13
+ TIME_TO_LIVE = 60 # seconds
14
+ TIME_TO_LIVE = 5 # seconds
13
15
 
14
16
 
15
17
  def start_server(host=DEFAULT_HOST, port=DEFAULT_PORT):
@@ -65,7 +67,10 @@ class DSMQClientSideConnection:
65
67
  raise RuntimeError("Connection terminated by server")
66
68
  msg_str = data.decode("utf-8")
67
69
  msg = json.loads(msg_str)
68
- return msg
70
+ try:
71
+ return msg["message"]
72
+ except KeyError:
73
+ return ""
69
74
 
70
75
  def put(self, topic, msg):
71
76
  msg = json.dumps({"action": "put", "topic": topic, "message": msg})
@@ -76,8 +81,9 @@ def _handle_client_connection(socket_conn):
76
81
  sqlite_conn = sqlite3.connect("file:mem1?mode=memory&cache=shared")
77
82
  cursor = sqlite_conn.cursor()
78
83
 
79
- creation_time = time.time()
80
- last_read = {}
84
+ client_creation_time = time.time()
85
+ last_read_times = {}
86
+ time_of_last_purge = time.time()
81
87
 
82
88
  while True:
83
89
  data = socket_conn.recv(1024)
@@ -120,10 +126,10 @@ VALUES (:timestamp, :topic, :message)
120
126
 
121
127
  elif msg["action"] == "get":
122
128
  try:
123
- last_read_time = last_read[topic]
129
+ last_read_time = last_read_times[topic]
124
130
  except KeyError:
125
- last_read[topic] = creation_time
126
- last_read_time = last_read[topic]
131
+ last_read_times[topic] = client_creation_time
132
+ last_read_time = last_read_times[topic]
127
133
  msg["last_read_time"] = last_read_time
128
134
 
129
135
  # This block allows for multiple retries if the database
@@ -156,7 +162,7 @@ AND timestamp = a.min_time
156
162
  result = cursor.fetchall()[0]
157
163
  message = result[0]
158
164
  timestamp = result[1]
159
- last_read[topic] = timestamp
165
+ last_read_times[topic] = timestamp
160
166
  except IndexError:
161
167
  # Handle the case where no results are returned
162
168
  message = ""
@@ -166,6 +172,20 @@ AND timestamp = a.min_time
166
172
  else:
167
173
  print("Action must either be 'put' or 'get'")
168
174
 
175
+ # Periodically clean out messages from the queue that are
176
+ # past their sell buy date.
177
+ # This operation is pretty fast. I clock it at 12 us on my machine.
178
+ if time.time() - time_of_last_purge > TIME_TO_LIVE:
179
+ cursor.execute(
180
+ """
181
+ DELETE FROM messages
182
+ WHERE timestamp < :time_threshold
183
+ """,
184
+ {"time_threshold": time_of_last_purge}
185
+ )
186
+ sqlite_conn.commit()
187
+ time_of_last_purge = time.time()
188
+
169
189
  sqlite_conn.close()
170
190
 
171
191
 
@@ -1,4 +1,3 @@
1
- import json
2
1
  import time
3
2
  import dsmq
4
3
 
@@ -1,5 +1,3 @@
1
- import json
2
- import socket
3
1
  import time
4
2
  import dsmq
5
3
 
@@ -3,5 +3,5 @@ requires-python = ">=3.10"
3
3
 
4
4
  [[package]]
5
5
  name = "dsmq"
6
- version = "0.2.0"
6
+ version = "0.4.0"
7
7
  source = { editable = "." }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes