beanqueue 0.2.0__tar.gz → 0.2.2__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.
Files changed (28) hide show
  1. {beanqueue-0.2.0 → beanqueue-0.2.2}/PKG-INFO +2 -2
  2. {beanqueue-0.2.0 → beanqueue-0.2.2}/README.md +1 -1
  3. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/app.py +93 -1
  4. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/config.py +12 -0
  5. {beanqueue-0.2.0 → beanqueue-0.2.2}/pyproject.toml +1 -1
  6. {beanqueue-0.2.0 → beanqueue-0.2.2}/LICENSE +0 -0
  7. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/__init__.py +0 -0
  8. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/cmds/__init__.py +0 -0
  9. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/cmds/create_tables.py +0 -0
  10. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/cmds/process.py +0 -0
  11. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/cmds/submit.py +0 -0
  12. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/cmds/utils.py +0 -0
  13. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/constants.py +0 -0
  14. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/db/__init__.py +0 -0
  15. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/db/base.py +0 -0
  16. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/db/session.py +0 -0
  17. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/events.py +0 -0
  18. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/models/__init__.py +0 -0
  19. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/models/helpers.py +0 -0
  20. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/models/task.py +0 -0
  21. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/models/worker.py +0 -0
  22. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/processors/__init__.py +0 -0
  23. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/processors/processor.py +0 -0
  24. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/processors/registry.py +0 -0
  25. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/services/__init__.py +0 -0
  26. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/services/dispatch.py +0 -0
  27. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/services/worker.py +0 -0
  28. {beanqueue-0.2.0 → beanqueue-0.2.2}/bq/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: beanqueue
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: BeanQueue or BQ for short, PostgreSQL SKIP LOCK based worker queue library
5
5
  License: MIT
6
6
  Author: Fang-Pen Lin
@@ -151,7 +151,7 @@ config = bq.Config(
151
151
  app = bq.BeanQueue(config=config)
152
152
  ```
153
153
 
154
- Then you can pass `--app` argument pointing to the app object to the process command like this:
154
+ Then you can pass `--app` argument (or `-a` for short) pointing to the app object to the process command like this:
155
155
 
156
156
  ```bash
157
157
  python -m bq.cmds.process -a my_pkgs.bq.app images
@@ -131,7 +131,7 @@ config = bq.Config(
131
131
  app = bq.BeanQueue(config=config)
132
132
  ```
133
133
 
134
- Then you can pass `--app` argument pointing to the app object to the process command like this:
134
+ Then you can pass `--app` argument (or `-a` for short) pointing to the app object to the process command like this:
135
135
 
136
136
  ```bash
137
137
  python -m bq.cmds.process -a my_pkgs.bq.app images
@@ -1,11 +1,14 @@
1
1
  import functools
2
2
  import importlib
3
+ import json
3
4
  import logging
4
5
  import platform
5
6
  import sys
6
7
  import threading
7
8
  import time
8
9
  import typing
10
+ from wsgiref.simple_server import make_server
11
+ from wsgiref.simple_server import WSGIRequestHandler
9
12
 
10
13
  import venusian
11
14
  from sqlalchemy import func
@@ -29,6 +32,21 @@ from .utils import load_module_var
29
32
  logger = logging.getLogger(__name__)
30
33
 
31
34
 
35
+ class WSGIRequestHandlerWithLogger(WSGIRequestHandler):
36
+ logger = logging.getLogger("metrics_server")
37
+
38
+ def log_message(self, format, *args):
39
+ message = format % args
40
+ self.logger.info(
41
+ "%s - - [%s] %s\n"
42
+ % (
43
+ self.address_string(),
44
+ self.log_date_time_string(),
45
+ message.translate(self._control_char_table),
46
+ )
47
+ )
48
+
49
+
32
50
  class BeanQueue:
33
51
  def __init__(
34
52
  self,
@@ -150,7 +168,9 @@ class BeanQueue:
150
168
  # is set too short. It could also be the administrator update the worker state to something else than
151
169
  # RUNNING. Regardless the reason, let's stop processing.
152
170
  logger.warning(
153
- "Current worker %s state is %s instead of running, quit processing"
171
+ "Current worker %s state is %s instead of running, quit processing",
172
+ current_worker.id,
173
+ current_worker.state,
154
174
  )
155
175
  sys.exit(0)
156
176
 
@@ -159,6 +179,64 @@ class BeanQueue:
159
179
  db.add(current_worker)
160
180
  db.commit()
161
181
 
182
+ def _serve_http_request(
183
+ self, worker_id: typing.Any, environ: dict, start_response: typing.Callable
184
+ ) -> list[bytes]:
185
+ path = environ["PATH_INFO"]
186
+ if path == "/healthz":
187
+ db = self.make_session()
188
+ worker_service = self._make_worker_service(db)
189
+ worker = worker_service.get_worker(worker_id)
190
+ if worker is not None and worker.state == models.WorkerState.RUNNING:
191
+ start_response(
192
+ "200 OK",
193
+ [
194
+ ("Content-Type", "application/json"),
195
+ ],
196
+ )
197
+ return [
198
+ json.dumps(dict(status="ok", worker_id=str(worker_id))).encode(
199
+ "utf8"
200
+ )
201
+ ]
202
+ else:
203
+ logger.warning("Bad worker %s state %s", worker_id, worker.state)
204
+ start_response(
205
+ "500 Internal Server Error",
206
+ [
207
+ ("Content-Type", "application/json"),
208
+ ],
209
+ )
210
+ return [
211
+ json.dumps(
212
+ dict(
213
+ status="internal error",
214
+ worker_id=str(worker_id),
215
+ state=str(worker.state),
216
+ )
217
+ ).encode("utf8")
218
+ ]
219
+ # TODO: add other metrics endpoints
220
+ start_response(
221
+ "404 NOT FOUND",
222
+ [
223
+ ("Content-Type", "application/json"),
224
+ ],
225
+ )
226
+ return [json.dumps(dict(status="not found")).encode("utf8")]
227
+
228
+ def run_metrics_http_server(self, worker_id: typing.Any):
229
+ host = self.config.METRICS_HTTP_SERVER_INTERFACE
230
+ port = self.config.METRICS_HTTP_SERVER_PORT
231
+ with make_server(
232
+ host,
233
+ port,
234
+ functools.partial(self._serve_http_request, worker_id),
235
+ handler_class=WSGIRequestHandlerWithLogger,
236
+ ) as httpd:
237
+ logger.info("Run metrics HTTP server on %s:%s", host, port)
238
+ httpd.serve_forever()
239
+
162
240
  def process_tasks(
163
241
  self,
164
242
  channels: tuple[str, ...],
@@ -194,6 +272,18 @@ class BeanQueue:
194
272
  dispatch_service.listen(channels)
195
273
  db.commit()
196
274
 
275
+ metrics_server_thread = None
276
+ if self.config.METRICS_HTTP_SERVER_ENABLED:
277
+ WSGIRequestHandlerWithLogger.logger.setLevel(
278
+ self.config.METRICS_HTTP_SERVER_LOG_LEVEL
279
+ )
280
+ metrics_server_thread = threading.Thread(
281
+ target=self.run_metrics_http_server,
282
+ args=(worker.id,),
283
+ )
284
+ metrics_server_thread.daemon = True
285
+ metrics_server_thread.start()
286
+
197
287
  logger.info("Created worker %s, name=%s", worker.id, worker.name)
198
288
  events.worker_init.send(self, worker=worker)
199
289
 
@@ -249,6 +339,8 @@ class BeanQueue:
249
339
  db.rollback()
250
340
  logger.info("Shutting down ...")
251
341
  worker_update_thread.join(5)
342
+ if metrics_server_thread is not None:
343
+ metrics_server_thread.join(5)
252
344
 
253
345
  worker.state = models.WorkerState.SHUTDOWN
254
346
  db.add(worker)
@@ -30,6 +30,18 @@ class Config(BaseSettings):
30
30
  # which worker model to use
31
31
  WORKER_MODEL: str = "bq.Worker"
32
32
 
33
+ # Enable metrics HTTP server
34
+ METRICS_HTTP_SERVER_ENABLED: bool = True
35
+
36
+ # the metrics http server interface to listen
37
+ METRICS_HTTP_SERVER_INTERFACE: str = ""
38
+
39
+ # the metrics http server port to listen
40
+ METRICS_HTTP_SERVER_PORT: int = 8000
41
+
42
+ # default log level for metrics http server
43
+ METRICS_HTTP_SERVER_LOG_LEVEL: int = 30
44
+
33
45
  POSTGRES_SERVER: str = "localhost"
34
46
  POSTGRES_USER: str = "bq"
35
47
  POSTGRES_PASSWORD: str = ""
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "beanqueue"
3
- version = "0.2.0"
3
+ version = "0.2.2"
4
4
  description = "BeanQueue or BQ for short, PostgreSQL SKIP LOCK based worker queue library"
5
5
  authors = ["Fang-Pen Lin <fangpen@launchplatform.com>"]
6
6
  license = "MIT"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes