baqueue 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,609 @@
1
+ Metadata-Version: 2.4
2
+ Name: baqueue
3
+ Version: 0.1.0
4
+ Summary: A powerful Python queue management package inspired by Laravel Horizon
5
+ Author: Basalam, BaQueue Contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/basalam/baqueue
8
+ Project-URL: Repository, https://github.com/basalam/baqueue
9
+ Project-URL: Issues, https://github.com/basalam/baqueue/issues
10
+ Project-URL: Changelog, https://github.com/basalam/baqueue/releases
11
+ Keywords: queue,job,worker,scheduler,horizon,redis,postgres,async,task
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Framework :: AsyncIO
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Software Development :: Libraries
23
+ Classifier: Topic :: System :: Distributed Computing
24
+ Requires-Python: >=3.10
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: pydantic>=2.0
28
+ Requires-Dist: click>=8.0
29
+ Requires-Dist: croniter>=2.0
30
+ Provides-Extra: redis
31
+ Requires-Dist: redis[hiredis]>=5.0; extra == "redis"
32
+ Provides-Extra: postgres
33
+ Requires-Dist: asyncpg>=0.29; extra == "postgres"
34
+ Provides-Extra: dashboard
35
+ Requires-Dist: fastapi>=0.110; extra == "dashboard"
36
+ Requires-Dist: uvicorn[standard]>=0.29; extra == "dashboard"
37
+ Requires-Dist: websockets>=12.0; extra == "dashboard"
38
+ Provides-Extra: all
39
+ Requires-Dist: redis[hiredis]>=5.0; extra == "all"
40
+ Requires-Dist: asyncpg>=0.29; extra == "all"
41
+ Requires-Dist: fastapi>=0.110; extra == "all"
42
+ Requires-Dist: uvicorn[standard]>=0.29; extra == "all"
43
+ Requires-Dist: websockets>=12.0; extra == "all"
44
+ Provides-Extra: dev
45
+ Requires-Dist: baqueue[all]; extra == "dev"
46
+ Requires-Dist: pytest>=8.0; extra == "dev"
47
+ Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
48
+ Requires-Dist: build>=1.0; extra == "dev"
49
+ Requires-Dist: twine>=5.0; extra == "dev"
50
+ Dynamic: license-file
51
+
52
+ # BaQueue
53
+
54
+ [![PyPI version](https://img.shields.io/pypi/v/baqueue.svg)](https://pypi.org/project/baqueue/)
55
+ [![Python versions](https://img.shields.io/pypi/pyversions/baqueue.svg)](https://pypi.org/project/baqueue/)
56
+ [![License: MIT](https://img.shields.io/pypi/l/baqueue.svg)](https://github.com/basalam/baqueue/blob/master/LICENSE)
57
+ [![CI](https://github.com/basalam/baqueue/actions/workflows/ci.yml/badge.svg)](https://github.com/basalam/baqueue/actions/workflows/ci.yml)
58
+
59
+ A powerful Python queue management package. Multi-driver support, batch jobs, scheduling, auto-balancing, and a beautiful real-time monitoring dashboard.
60
+
61
+ ![Overview](./baqueue/screen/1.png)
62
+
63
+ ### Jobs - Filterable job list with status, attempts, and duration
64
+ ![Jobs](./baqueue/screen/2.png)
65
+
66
+ ### Queues - Per-queue detail cards with pending/processing/completed/failed
67
+ ![Queues](./baqueue/screen/3.png)
68
+
69
+ ## Table of Contents
70
+
71
+ - [Features](#features)
72
+ - [Quick Start](#quick-start)
73
+ - [Define a Job](#define-a-job)
74
+ - [Dispatch Jobs](#dispatch-jobs)
75
+ - [Batch Jobs](#batch-jobs)
76
+ - [Run Workers](#run-workers)
77
+ - [Pruning](#pruning)
78
+ - [Auto-pruning](#auto-pruning-runs-alongside-baqueue-work)
79
+ - [Manual pruning](#manual-pruning)
80
+ - [Retry Failed Jobs](#retry-failed-jobs)
81
+ - [Dashboard](#dashboard)
82
+ - [Workers Tab (Supervisor/Worker Monitoring)](#workers-tab-supervisorworker-monitoring)
83
+ - [Drivers](#drivers)
84
+ - [Examples](#examples)
85
+ - [Testing](#testing)
86
+ - [CLI Commands](#cli-commands)
87
+ - [Benchmarks](#benchmarks)
88
+ - [Test 1: 1,000 jobs / 5 workers](#test-1-1000-jobs--5-workers)
89
+ - [Test 2: 5,000 jobs / 10 workers](#test-2-5000-jobs--10-workers)
90
+ - [Stress Test Options](#stress-test-options)
91
+ - [Run with Live Dashboard](#run-with-live-dashboard)
92
+ - [License](#license)
93
+
94
+ ## Features
95
+ - **Multi-driver**: SQLite (default), Redis, PostgreSQL, or In-Memory
96
+ - **Auto-balancing**: Dynamically scale workers based on queue pressure
97
+ - **Auto-pruning**: Completed jobs are deleted about 5 seconds after they finish; failed/cancelled jobs are kept up to 1 day — all configurable
98
+ - **Disk-full cleanup**: Storage-full/OOM driver errors trigger emergency cleanup of terminal jobs and old metrics, then retry once
99
+ - **Pruning**: Remove old jobs by status, tag, or age
100
+ - **Monitoring Dashboard**: Real-time WebSocket-powered UI with date filtering
101
+ - **CLI**: Manage workers, scheduler, dashboard, and pruning from the command line
102
+ - **Cross-process**: SQLite driver shares state between dashboard and workers without external dependencies
103
+
104
+ ## Quick Start
105
+
106
+ ```bash
107
+ # Install (SQLite + in-memory drivers work out of the box, zero extra dependencies)
108
+ pip install baqueue
109
+
110
+ # With Redis support
111
+ pip install "baqueue[redis]"
112
+
113
+ # With PostgreSQL support
114
+ pip install "baqueue[postgres]"
115
+
116
+ # With dashboard
117
+ pip install "baqueue[dashboard]"
118
+
119
+ # Everything
120
+ pip install "baqueue[all]"
121
+ ```
122
+
123
+ > **Installing from source (development):**
124
+ > ```bash
125
+ > git clone https://github.com/basalam/baqueue.git
126
+ > cd baqueue
127
+ > pip install -e ".[dev]" # editable install with all extras + test/build tooling
128
+ > ```
129
+
130
+ ### Define a Job
131
+
132
+ ```python
133
+ from baqueue import Job
134
+
135
+ class SendEmail(Job):
136
+ queue = "emails"
137
+ max_attempts = 3
138
+ backoff = "exponential"
139
+
140
+ async def handle(self, to: str, subject: str, body: str):
141
+ await send_email(to, subject, body)
142
+
143
+ async def on_failure(self, error, payload):
144
+ print(f"Failed to send email: {error}")
145
+ ```
146
+
147
+ Or use the decorator:
148
+
149
+ ```python
150
+ from baqueue import Job
151
+
152
+ @Job.as_job(queue="emails", max_attempts=3)
153
+ async def send_email(to, subject, body):
154
+ ...
155
+ ```
156
+
157
+ ### Dispatch Jobs
158
+
159
+ ```python
160
+ from baqueue import Queue, BaQueueConfig
161
+ from baqueue.config import DriverConfig
162
+
163
+ # Configure (SQLite driver by default - works across processes)
164
+ Queue.configure(BaQueueConfig(driver=DriverConfig(name="sqlite")))
165
+ await Queue.connect()
166
+
167
+ # Push a job
168
+ await Queue.push(SendEmail, to="user@example.com", subject="Hi", body="Hello!")
169
+
170
+ # Push with delay (60 seconds)
171
+ await Queue.later(SendEmail, delay=60, to="user@example.com", subject="Reminder", body="...")
172
+
173
+ # Bulk push (much faster for large volumes)
174
+ await Queue.bulk([
175
+ (SendEmail, {"to": "a@b.com", "subject": "Hi", "body": "A"}),
176
+ (SendEmail, {"to": "c@d.com", "subject": "Hi", "body": "B"}),
177
+ ])
178
+ ```
179
+
180
+ ### Batch Jobs
181
+
182
+ ```python
183
+ from baqueue import Batch
184
+
185
+ result = await Batch(driver, [
186
+ (SendEmail, {"to": "a@b.com", "subject": "Hi", "body": "Hey"}),
187
+ (SendEmail, {"to": "c@d.com", "subject": "Hi", "body": "Hey"}),
188
+ ]).name("newsletter").then(OnAllDone).catch(OnAnyFailed).dispatch()
189
+ ```
190
+
191
+ ### Run Workers
192
+
193
+ ```python
194
+ from baqueue.supervisor import Supervisor
195
+ from baqueue.config import SupervisorConfig
196
+
197
+ supervisor = Supervisor(
198
+ driver=Queue.get_driver(),
199
+ config=SupervisorConfig(
200
+ queues=["emails", "payments"],
201
+ min_workers=3,
202
+ max_workers=10,
203
+ balance="auto",
204
+ ),
205
+ )
206
+ await supervisor.start()
207
+ ```
208
+
209
+ Or via CLI:
210
+
211
+ ```bash
212
+ baqueue work -q emails -q payments -w 3 -b auto
213
+ ```
214
+
215
+ ### Pruning
216
+
217
+ #### Auto-pruning (runs alongside `baqueue work`)
218
+
219
+ When `baqueue work` is running, a background pruner cycles every 5s and applies these defaults across every driver:
220
+
221
+ | Status | Default lifetime | Config field |
222
+ |---------------------|------------------|-----------------------------|
223
+ | `completed` | 5 seconds | `prune_completed_seconds` |
224
+ | `failed`, `cancelled` | 1 day | `prune_other_seconds` |
225
+ | metrics rows | 7 days | `prune_metrics_seconds` |
226
+ | pruner cycle | every 5s | `prune_interval_seconds` |
227
+ | enable/disable | `True` | `auto_prune` |
228
+
229
+ Override from a JSON config file (`baqueue -c config.json work`):
230
+
231
+ ```json
232
+ {
233
+ "auto_prune": true,
234
+ "prune_completed_seconds": 600,
235
+ "prune_other_seconds": 172800,
236
+ "prune_interval_seconds": 30,
237
+ "auto_cleanup_on_disk_full": true
238
+ }
239
+ ```
240
+
241
+ Or from Python:
242
+
243
+ ```python
244
+ from baqueue import BaQueueConfig
245
+ config = BaQueueConfig(
246
+ prune_completed_seconds=600, # 10 minutes
247
+ prune_other_seconds=172800, # 2 days
248
+ prune_interval_seconds=30,
249
+ auto_cleanup_on_disk_full=True, # enabled by default
250
+ )
251
+ ```
252
+
253
+ Or from the CLI:
254
+
255
+ ```bash
256
+ baqueue work --prune-completed-seconds 600 --prune-other-seconds 172800
257
+ baqueue work --no-auto-prune # disable the background pruner
258
+ baqueue work --no-disk-full-cleanup # disable emergency storage cleanup
259
+ ```
260
+
261
+ The legacy hour-based fields (`prune_completed_hours`, `prune_failed_hours`, `prune_cancelled_hours`, `prune_metrics_hours`) are still respected for backward compatibility — when set to a positive value they override the corresponding `*_seconds` field.
262
+
263
+ #### Disk-full emergency cleanup
264
+
265
+ `auto_cleanup_on_disk_full` is enabled by default. When a driver write/update/delete operation sees a storage-full style error (SQLite disk full, PostgreSQL disk/memory exhausted, Redis OOM/maxmemory), BaQueue runs an emergency cleanup that removes terminal jobs (`completed`, `failed`, `cancelled`) and old metrics, then retries the failed operation once. If cleanup does not free enough space, the original driver error is still raised.
266
+
267
+ #### Manual pruning
268
+
269
+ ```python
270
+ # Remove completed jobs older than 24 hours
271
+ await Queue.prune(status="completed", hours=24)
272
+
273
+ # Remove jobs by tag
274
+ await Queue.prune(tag="batch:newsletter")
275
+ ```
276
+
277
+ ### Retry Failed Jobs
278
+
279
+ Bulk-retry failed jobs from the CLI, from Python, or from the dashboard.
280
+
281
+ **CLI:**
282
+
283
+ ```bash
284
+ # Retry every failed job (asks for confirmation)
285
+ baqueue retry-failed
286
+
287
+ # Skip the confirmation prompt
288
+ baqueue retry-failed -y
289
+
290
+ # Limit to a specific queue
291
+ baqueue retry-failed -q emails
292
+
293
+ # Combine filters: queue + tag + age window
294
+ baqueue retry-failed -q emails -t campaign --hours 24
295
+
296
+ # Use a non-default driver
297
+ baqueue retry-failed -d redis --driver-url redis://localhost:6379/0
298
+ ```
299
+
300
+ **Python:**
301
+
302
+ ```python
303
+ # Retry every failed job
304
+ count = await Queue.retry_failed()
305
+
306
+ # Retry only failed jobs in a queue
307
+ count = await Queue.retry_failed(queue="emails")
308
+
309
+ # Filter by tag and creation window
310
+ from baqueue.serializer import _now_ts
311
+ count = await Queue.retry_failed(
312
+ queue="emails",
313
+ tag="campaign",
314
+ created_from=_now_ts() - 24 * 3600,
315
+ )
316
+ ```
317
+
318
+ **Dashboard:** open the **Jobs** tab, set the Status filter to `Failed`, then click the amber **Retry All** button. The current Queue / Tag / date-range filters are respected.
319
+
320
+ Each matched job is released back onto its queue with `delay=0`, the same path used by single-job retry.
321
+
322
+ ### Dashboard
323
+
324
+ ```bash
325
+ # Start the dashboard (uses SQLite by default)
326
+ baqueue dashboard
327
+
328
+ # Open http://localhost:9100
329
+ ```
330
+
331
+ The dashboard includes:
332
+ - Real-time overview with pending/processing/completed/failed counters sourced from live job state (not bounded metric logs)
333
+ - Date range filtering (custom range + presets: 1h, 24h, 7d, 30d)
334
+ - Job detail modal with timeline, payload data, and error trace
335
+ - Queue breakdown with progress bars
336
+ - Worker monitoring with active/idle status
337
+ - Dark/light theme toggle
338
+ - **Scheduled-job badge** with hover tooltip showing exact execution time, plus a "Scheduled For" entry in the job timeline
339
+ - **Bulk "Retry All"** button when the Jobs view is filtered to `failed` (respects the active queue/tag/date filters)
340
+ - **Queue filter as a dropdown** auto-populated from active queues (no manual typing)
341
+ - **Mobile-friendly** sidebar drawer with hamburger toggle on screens ≤900px
342
+
343
+ Run in one terminal:
344
+ ```bash
345
+ baqueue dashboard
346
+ ```
347
+
348
+ Dispatch jobs in another terminal:
349
+ ```bash
350
+ python examples/simple_job.py
351
+ ```
352
+
353
+ #### Workers Tab (Supervisor/Worker Monitoring)
354
+
355
+ To see active supervisors/workers in the `Workers` tab, `work` and `dashboard`
356
+ must point to the same backend (same driver and same URL/path).
357
+
358
+ Example with SQLite:
359
+
360
+ Terminal 1:
361
+ ```bash
362
+ baqueue work -d sqlite --driver-url .baqueue.db -q default -w 3
363
+ ```
364
+
365
+ Terminal 2:
366
+ ```bash
367
+ baqueue dashboard -d sqlite --driver-url .baqueue.db
368
+ ```
369
+
370
+ Then open:
371
+ ```text
372
+ http://localhost:9100
373
+ ```
374
+
375
+ Quick troubleshooting:
376
+ - Check `http://localhost:9100/api/supervisors` (should return a non-empty `supervisors` list while workers are running).
377
+ - If `api/supervisors` is empty, `work` and `dashboard` are likely using different driver URLs/paths.
378
+ - `memory` driver is single-process only, so separate `work` and `dashboard` processes will not share worker state.
379
+
380
+ Driver-specific CLI examples:
381
+
382
+ SQLite (shared local file):
383
+ ```bash
384
+ baqueue work -d sqlite --driver-url .baqueue.db -q default -w 3
385
+ baqueue dashboard -d sqlite --driver-url .baqueue.db
386
+ ```
387
+
388
+ Redis (shared Redis DB):
389
+ ```bash
390
+ baqueue work -d redis --driver-url redis://localhost:6379/0 -q default -w 3
391
+ baqueue dashboard -d redis --driver-url redis://localhost:6379/0
392
+ ```
393
+
394
+ PostgreSQL (shared database/schema):
395
+ ```bash
396
+ baqueue work -d postgres --driver-url postgresql://user:pass@localhost/dbname -q default -w 3
397
+ baqueue dashboard -d postgres --driver-url postgresql://user:pass@localhost/dbname
398
+ ```
399
+
400
+ Memory (single-process only):
401
+ ```bash
402
+ # Use an in-process example to run workers + dashboard together.
403
+ python examples/dashboard_demo.py
404
+ ```
405
+
406
+ ### Drivers
407
+
408
+ **SQLite (default, zero-config, cross-process):**
409
+ ```python
410
+ Queue.configure(BaQueueConfig(
411
+ driver=DriverConfig(name="sqlite")
412
+ ))
413
+ ```
414
+
415
+ **Redis:**
416
+ ```python
417
+ Queue.configure(BaQueueConfig(
418
+ driver=DriverConfig(name="redis", url="redis://localhost:6379/0")
419
+ ))
420
+ ```
421
+
422
+ **PostgreSQL:**
423
+ ```python
424
+ Queue.configure(BaQueueConfig(
425
+ driver=DriverConfig(name="postgres", url="postgresql://user:pass@localhost/dbname")
426
+ ))
427
+ ```
428
+
429
+ **Memory (single-process testing only):**
430
+ ```python
431
+ Queue.configure(BaQueueConfig(
432
+ driver=DriverConfig(name="memory")
433
+ ))
434
+ ```
435
+
436
+ ## Examples
437
+
438
+ ```bash
439
+ # Simple job processing
440
+ python examples/simple_job.py
441
+
442
+ # Batch processing
443
+ python examples/batch_example.py
444
+
445
+ # Scheduled jobs
446
+ python examples/scheduled_example.py
447
+
448
+ # Dashboard demo (open http://localhost:9100)
449
+ python examples/dashboard_demo.py
450
+
451
+ # Delayed jobs demo — shows the "Scheduled" badge with varied delays
452
+ python examples/delayed_jobs_demo.py
453
+
454
+ # Stress test (see Benchmarks section below)
455
+ python examples/stress_test.py --jobs 1000 --workers 5 --bulk
456
+ ```
457
+
458
+ ## Testing
459
+
460
+ The full test suite lives in `tests/` and runs with one command:
461
+
462
+ ```bash
463
+ # Run everything
464
+ baqueue test
465
+
466
+ # Quiet output, stop at the first failure
467
+ baqueue test -q -x
468
+
469
+ # Run only retry-failed related tests
470
+ baqueue test -k "RetryFailed or retry_failed"
471
+
472
+ # Re-run just the tests that failed last time
473
+ baqueue test --last-failed
474
+
475
+ # Filter by marker (markers defined in pyproject.toml)
476
+ baqueue test -m "not slow"
477
+ ```
478
+
479
+ `baqueue test` is a thin wrapper around `pytest`, so it picks up the project's
480
+ `tool.pytest.ini_options` config (asyncio mode, marker definitions, etc.).
481
+ You can also run pytest directly:
482
+
483
+ ```bash
484
+ pip install baqueue[dev]
485
+ pytest tests/ -v
486
+ ```
487
+
488
+ Coverage includes:
489
+
490
+ - Serializer / payload roundtrip (incl. `delay_until`)
491
+ - Backoff strategies (`fixed`, `linear`, `exponential`, explicit list)
492
+ - `Job` + `FunctionJob` + `@Job.as_job` decorator
493
+ - `Queue` facade — push / later / bulk / prune / `retry_failed`
494
+ - Cross-driver contract tests (memory + sqlite, parameterized)
495
+ - Worker lifecycle: success / failure / retry / timeout
496
+ - Supervisor pool + delayed-job promotion
497
+ - Scheduler interval dispatch
498
+ - Pruner by status / tag / age
499
+ - Batch builder + completion callbacks
500
+ - DashboardAPI (overview, jobs_list, retry, bulk retry-failed, prune, stats)
501
+ - CLI command surface (help text, validation, `retry-failed` abort flow)
502
+
503
+ ## CLI Commands
504
+
505
+ ```
506
+ baqueue work Start processing jobs
507
+ baqueue schedule Start the job scheduler
508
+ baqueue dashboard Launch the monitoring dashboard
509
+ baqueue prune Prune old jobs
510
+ baqueue retry-failed Retry all failed jobs (filter by queue/tag/age)
511
+ baqueue status Show queue status
512
+ baqueue test Run the test suite
513
+ ```
514
+
515
+ Use `-h` on any command for options:
516
+ ```bash
517
+ baqueue -h
518
+ baqueue work -h
519
+ baqueue dashboard -h
520
+ ```
521
+
522
+ ## Benchmarks
523
+
524
+ Stress tests run on **Windows 10, Python 3.11, SQLite driver**, using `examples/stress_test.py`.
525
+
526
+ The stress test dispatches jobs across 5 queues (`fast`, `slow`, `flaky`, `heavy`, `notifications`) with varying execution times and a ~30% failure rate on the `flaky` queue, exercising retries and backoff.
527
+
528
+ ### Test 1: 1,000 jobs / 5 workers
529
+
530
+ ```bash
531
+ python examples/stress_test.py --jobs 1000 --workers 5 --bulk
532
+ ```
533
+
534
+ ```
535
+ ============================================================
536
+ RESULTS
537
+ ============================================================
538
+ Total time: 30.38s
539
+ Completed: 993
540
+ Failed: 7
541
+ Throughput: 32.9 jobs/s
542
+ Success rate: 99.3%
543
+ ============================================================
544
+ ```
545
+
546
+ | Metric | Value |
547
+ |-------------------|----------------|
548
+ | Dispatch speed | 28,426 jobs/s |
549
+ | Processing speed | 32.9 jobs/s |
550
+ | Total time | 30.4s |
551
+ | Success rate | 99.3% |
552
+
553
+ ### Test 2: 5,000 jobs / 10 workers
554
+
555
+ ```bash
556
+ python examples/stress_test.py --jobs 5000 --workers 10 --bulk
557
+ ```
558
+
559
+ ```
560
+ ============================================================
561
+ RESULTS
562
+ ============================================================
563
+ Total time: 49.95s
564
+ Completed: 4965
565
+ Failed: 35
566
+ Throughput: 100.1 jobs/s
567
+ Success rate: 99.3%
568
+ ============================================================
569
+ ```
570
+
571
+ | Metric | Value |
572
+ |-------------------|----------------|
573
+ | Dispatch speed | ~50,000 jobs/s |
574
+ | Processing speed | 100.1 jobs/s |
575
+ | Total time | 49.9s |
576
+ | Success rate | 99.3% |
577
+
578
+ ### Stress Test Options
579
+
580
+ ```bash
581
+ python examples/stress_test.py [OPTIONS]
582
+
583
+ Options:
584
+ --jobs, -j Number of jobs to dispatch (default: 1000)
585
+ --workers, -w Number of concurrent workers (default: 5)
586
+ --bulk Use bulk insert for faster dispatching
587
+ --dashboard Launch live dashboard on http://localhost:9100
588
+ ```
589
+
590
+ **Job types used in the stress test:**
591
+
592
+ | Job | Queue | Latency | Failure Rate | Max Attempts |
593
+ |-----------|-----------------|----------------|--------------|--------------|
594
+ | FastJob | `fast` | 10-50ms | 0% | 3 |
595
+ | SlowJob | `slow` | 100-300ms | 0% | 2 |
596
+ | FlakyJob | `flaky` | 20-80ms | ~30% | 3 |
597
+ | HeavyJob | `heavy` | 50-150ms | 0% | 1 |
598
+ | Notify | `notifications` | 10-40ms | 0% | 2 |
599
+
600
+ ### Run with Live Dashboard
601
+
602
+ ```bash
603
+ python examples/stress_test.py --jobs 3000 --workers 8 --bulk --dashboard
604
+ # Open http://localhost:9100 to watch progress in real-time
605
+ ```
606
+
607
+ ## License
608
+
609
+ [MIT](./LICENSE) © Basalam and BaQueue Contributors
@@ -0,0 +1,32 @@
1
+ baqueue/__init__.py,sha256=g-SUwicAvMHk_Kvo47cdmL7t5aLF5ECFiGtlkDRV5X8,435
2
+ baqueue/balancer.py,sha256=A3oZUgNMJeYTLE48IdX5W4DobQ-a66YA6u1PbJCmEFo,2962
3
+ baqueue/batch.py,sha256=PyJUhA8e9eP4Mxbc9xqDC4LuEnHMSr8knQkNOVU1Sn0,5828
4
+ baqueue/cli.py,sha256=D7csbeg-gcOjSTCaaO-Eb7bXcHbPHPRtS1PfExv0SmM,15826
5
+ baqueue/config.py,sha256=oxjXOEvSLHI-SOPTMk9mV-TsNoYfIyFfTk3qjWmGMzM,2815
6
+ baqueue/events.py,sha256=uEo_2ZqCt6NDEya585JNP2TiSfM9RLkSK9AO20B2WBw,1956
7
+ baqueue/job.py,sha256=URKCL2e7FJQhGLHgjwU6MF7nBux1RDm3Edb3doYQ0Q8,3840
8
+ baqueue/pruner.py,sha256=WYcDeqhv-Csc2OWbBekjH3gZOAyoK7ZMOksu8F9RNsk,4496
9
+ baqueue/queue.py,sha256=jUxXEPKXt0MdfytgJ1M-tAdqpSXQhIuNmfKA5xi0XZM,8555
10
+ baqueue/retry.py,sha256=WE-16BvYjxY1OTdo2mUnWVCPnPV-_iep2l5LXTRPSks,1490
11
+ baqueue/scheduler.py,sha256=QcVJcZZaHkqyogW80uMPHr7SefZqUFVmgFt3FOX4vrs,3358
12
+ baqueue/serializer.py,sha256=ot4zXS5m7cbKnlfAL5voO5ZX72PqYuTA9-DFsu9VG50,3545
13
+ baqueue/supervisor.py,sha256=TrR_oc6-wj9hctweMuccPrC3-wJis7f5FfFdcOSZaYE,6881
14
+ baqueue/worker.py,sha256=xLUa19nBh4eZZPbyKX4V2IoGbfP9oz8RMFIQMKocUy8,6246
15
+ baqueue/dashboard/__init__.py,sha256=NalXBkAM8bFY1tAvzSO4SUToqqzIGI7LKlO5c10uG6o,36
16
+ baqueue/dashboard/api.py,sha256=TFecWuYsrZu-udvV8lvkYPC6WsNkf_Bos1TkGm8S1tE,6977
17
+ baqueue/dashboard/server.py,sha256=pzv5evhFtdklcn-lUu2KzRFmZsTCSj81YRYQeqN-viM,9384
18
+ baqueue/dashboard/static/app.js,sha256=ebxOmHaha5Sgd2gP_YVd8vxQZ9z9XZq5YhZ7NJDItk4,15016
19
+ baqueue/dashboard/static/index.html,sha256=pLpr5u5w_xBqheur-V0Yn8-nxt0d6FrQB-Al9HfG_F8,39111
20
+ baqueue/dashboard/static/style.css,sha256=NFJYyVazfc5TDOosMno8xU2f2pyOFZ8-ZkgahVuSv4U,37564
21
+ baqueue/drivers/__init__.py,sha256=S2PcgKJqZmBu9Cv5hcyTER5xovAPlLKEuuk5JtoRfcw,38
22
+ baqueue/drivers/base.py,sha256=SYcWIYyJBDhAQq8DFYAHGea1nbh3-MDibXe1EtlERt4,7912
23
+ baqueue/drivers/memory_driver.py,sha256=mucdW90W7XaJW_zlL_4cP2GoiFGpEvThhoNC8i3kp4s,11989
24
+ baqueue/drivers/postgres_driver.py,sha256=vRDnJ0suiNb1GtLJVQPCVedm2y8ey8kdVJK54EzuBuM,26033
25
+ baqueue/drivers/redis_driver.py,sha256=_TMkztClV5cPzW9IPI1fO9va6GLMpWPnNx7s5XD6jIY,26303
26
+ baqueue/drivers/sqlite_driver.py,sha256=nbbmlZ4Zi2vBeq2tMg730ohMGgp1bgDp6Le5ZbFZGwA,28429
27
+ baqueue-0.1.0.dist-info/licenses/LICENSE,sha256=m58-rcQ4uToYHQOdmfuUw9GqhGOir59G0QXaVA7n3F8,1089
28
+ baqueue-0.1.0.dist-info/METADATA,sha256=fKQ0fT4YOG4tCXIa5Ois1T0bm2_V4oPInw_Ed1UG_XM,18891
29
+ baqueue-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
30
+ baqueue-0.1.0.dist-info/entry_points.txt,sha256=sHCEK0xlNJK7qd7PMrQvS4mNGY8MLFnR_eFIfaJOoaw,44
31
+ baqueue-0.1.0.dist-info/top_level.txt,sha256=ipqrnd0xttQ_x-PEcugKkJkOLLUhxa3NCuV7l6rsq1c,8
32
+ baqueue-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ baqueue = baqueue.cli:cli
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Basalam and BaQueue Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ baqueue