wurk 0.0.3 → 0.0.5
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.
- checksums.yaml +4 -4
- data/README.md +20 -2
- data/lib/wurk/version.rb +1 -1
- data/vendor/assets/dashboard/assets/index-D2XR0iGw.js +60 -0
- data/vendor/assets/dashboard/assets/index-DlPr4YXw.css +1 -0
- data/vendor/assets/dashboard/index.html +2 -2
- data/vendor/assets/dashboard/wurk-manifest.json +2 -2
- metadata +3 -6
- data/CHANGELOG.md +0 -58
- data/CONTRIBUTING.md +0 -73
- data/SECURITY.md +0 -39
- data/vendor/assets/dashboard/assets/index-8P3N_m1X.js +0 -152
- data/vendor/assets/dashboard/assets/index-Bqz4_SOQ.css +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{--bg:#0f1117;--surface:#1a1d27;--border:#2a2d3e;--text:#e0e2f0;--text-muted:#6b7280;--accent:#7c6af7;--accent-hover:#9580ff;--danger:#ef4444;--warning:#f59e0b;--success:#22c55e;--nav-width:240px}[data-theme=light]{--bg:#f5f5f5;--surface:#fff;--border:#e0e0e0;--text:#1a1a2e;--text-muted:#6b7280}*{box-sizing:border-box;margin:0;padding:0}body{background:var(--bg);color:var(--text);font-family:system-ui,-apple-system,sans-serif;font-size:14px;line-height:1.5}a{color:var(--accent);text-decoration:none}a:hover{color:var(--accent-hover)}button{cursor:pointer;font-family:inherit;font-size:inherit}table{border-collapse:collapse;width:100%}th,td{text-align:left;border-bottom:1px solid var(--border);white-space:nowrap;text-overflow:ellipsis;max-width:300px;padding:.5rem .75rem;overflow:hidden}th{color:var(--text-muted);text-transform:uppercase;letter-spacing:.05em;background:var(--bg);z-index:1;font-size:12px;font-weight:500;position:sticky;top:0}tr:hover td{background:var(--border)}.hamburger{background:var(--surface);border:1px solid var(--border);color:var(--text);border-radius:4px;padding:.5rem;font-size:18px;line-height:1;display:none}@media (width<=767px){.hamburger{display:block}.main-content{margin-right:0!important;padding-top:3.5rem!important}}.badge{text-transform:uppercase;letter-spacing:.04em;border-radius:999px;padding:2px 8px;font-size:11px;font-weight:600;display:inline-block}.badge-success{color:var(--success);background:#22c55e26}.badge-danger{color:var(--danger);background:#ef444426}.badge-warning{color:var(--warning);background:#f59e0b26}.badge-muted{background:var(--border);color:var(--text-muted)}.badge-accent{color:var(--accent);background:#7c6af726}.card{background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:1rem}.progress-bar-track{background:var(--border);border-radius:999px;height:6px;overflow:hidden}.progress-bar-fill{border-radius:999px;height:100%;transition:width .3s}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.select{background:var(--surface);border:1px solid var(--border);color:var(--text);cursor:pointer;border-radius:4px;padding:.375rem .75rem;font-size:13px}.select:focus{outline:2px solid var(--accent);outline-offset:1px}.input{background:var(--surface);border:1px solid var(--border);color:var(--text);border-radius:4px;width:100%;padding:.5rem .75rem;font-size:14px}.input:focus{outline:2px solid var(--accent);outline-offset:1px}.btn{background:var(--surface);border:1px solid var(--border);color:var(--text);border-radius:4px;padding:.375rem .875rem;font-size:13px;transition:background .15s,border-color .15s}.btn:hover{border-color:var(--accent);color:var(--accent)}.btn-accent{background:var(--accent);border-color:var(--accent);color:#fff}.btn-accent:hover{background:var(--accent-hover);border-color:var(--accent-hover);color:#fff}.btn-danger{color:var(--danger);border-color:var(--danger)}.btn-danger:hover{background:var(--danger);color:#fff}.section-header{align-items:center;gap:.75rem;margin-bottom:1rem;display:flex}.section-title{font-size:16px;font-weight:600}.page-title{margin-bottom:1.5rem;font-size:22px;font-weight:700}.table-wrapper{border:1px solid var(--border);border-radius:8px;overflow-x:auto}.empty-state{text-align:center;color:var(--text-muted);padding:3rem}.live-dot{background:var(--success);border-radius:50%;width:8px;height:8px;animation:1.5s infinite pulse;display:inline-block}@keyframes pulse{0%,to{opacity:1}50%{opacity:.3}}.spinner{border:2px solid var(--border);border-top-color:var(--accent);border-radius:50%;width:20px;height:20px;animation:.7s linear infinite spin;display:inline-block}@keyframes spin{to{transform:rotate(360deg)}}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>Wurk</title>
|
|
7
|
-
<script type="module" crossorigin src="/wurk-assets/assets/index-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="/wurk-assets/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/wurk-assets/assets/index-D2XR0iGw.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/wurk-assets/assets/index-DlPr4YXw.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div id="wurk-root"></div>
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: wurk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- developerz.ai
|
|
@@ -88,11 +88,8 @@ executables:
|
|
|
88
88
|
extensions: []
|
|
89
89
|
extra_rdoc_files: []
|
|
90
90
|
files:
|
|
91
|
-
- CHANGELOG.md
|
|
92
|
-
- CONTRIBUTING.md
|
|
93
91
|
- LICENSE
|
|
94
92
|
- README.md
|
|
95
|
-
- SECURITY.md
|
|
96
93
|
- app/controllers/wurk/api/pagination.rb
|
|
97
94
|
- app/controllers/wurk/api/serializers.rb
|
|
98
95
|
- app/controllers/wurk/api_controller.rb
|
|
@@ -198,8 +195,8 @@ files:
|
|
|
198
195
|
- lib/wurk/work_set.rb
|
|
199
196
|
- lib/wurk/worker.rb
|
|
200
197
|
- lib/wurk/worker/setter.rb
|
|
201
|
-
- vendor/assets/dashboard/assets/index-
|
|
202
|
-
- vendor/assets/dashboard/assets/index-
|
|
198
|
+
- vendor/assets/dashboard/assets/index-D2XR0iGw.js
|
|
199
|
+
- vendor/assets/dashboard/assets/index-DlPr4YXw.css
|
|
203
200
|
- vendor/assets/dashboard/index.html
|
|
204
201
|
- vendor/assets/dashboard/wurk-manifest.json
|
|
205
202
|
homepage: https://github.com/developerz-ai/wurk
|
data/CHANGELOG.md
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to Wurk are recorded here. Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Versioning: [Semantic Versioning](https://semver.org/).
|
|
4
|
-
|
|
5
|
-
## [Unreleased]
|
|
6
|
-
|
|
7
|
-
### Added
|
|
8
|
-
- `Sidekiq::Testing` drop-in: `inline!` / `fake!` / `disable!` (global or block-scoped), the in-memory `Sidekiq::Queues` store, and the `Worker`/`Job` test helpers (`.jobs`, `.clear`, `.drain`, `.perform_one`, `.process_job`, `.drain_all`, `.clear_all`) + `Sidekiq::EmptyQueueError`.
|
|
9
|
-
|
|
10
|
-
## [0.0.3] - 2026-06-01
|
|
11
|
-
|
|
12
|
-
### Changed
|
|
13
|
-
- Gem contact email set to `admin@developerz.ai`.
|
|
14
|
-
|
|
15
|
-
## [0.0.2] - 2026-06-01
|
|
16
|
-
|
|
17
|
-
### Changed
|
|
18
|
-
- Releases now publish to RubyGems via GitHub Actions OIDC trusted publishing (`rubygems/release-gem`) — no long-lived API key. Pushing a `v*` tag cuts the release.
|
|
19
|
-
|
|
20
|
-
### Added
|
|
21
|
-
- Local release helpers: `bin/gem-build`, `bin/gem-login`, `bin/gem-push` for manual/bootstrap publishing.
|
|
22
|
-
|
|
23
|
-
## [0.0.1] - 2026-06-01
|
|
24
|
-
|
|
25
|
-
First public (pre-1.0) release. Wurk is a 100% API-compatible drop-in replacement for Sidekiq + Sidekiq Pro + Sidekiq Enterprise — same Redis key schema, same job JSON, same Ruby DSL — with fork-based real parallelism, the full Pro + Enterprise feature set in one free gem (no license check), and a precompiled React dashboard.
|
|
26
|
-
|
|
27
|
-
### Runtime
|
|
28
|
-
- Fork-based Swarm: parent forks N children with PID supervision, rolling restart (SIGUSR1), graceful drain (SIGTERM/SIGINT) to `shutdown_timeout`, and global pause/resume (SIGTSTP/SIGCONT).
|
|
29
|
-
- Reliable fetcher — atomic `BLMOVE` from the main queue to a per-process private list — with orphan reclamation on boot; Processor runs the middleware chain; Manager owns the thread pool, lifecycle, and heartbeat.
|
|
30
|
-
- Scheduled-set and retry pollers; EVALSHA-cached Lua on the hot paths; per-fork Redis pool over redis-client; Redis-outage client buffer.
|
|
31
|
-
- `reliable_push` opt-in `:raise` overflow policy with a background drainer.
|
|
32
|
-
- Cluster leader election with periodic firing consolidated onto the leader.
|
|
33
|
-
- StatsD metrics across hot paths; liveness HTTP endpoint for Kubernetes probes; expired-job counter for `expires_in`.
|
|
34
|
-
|
|
35
|
-
### Batches
|
|
36
|
-
- Sidekiq Pro Batch API: `on(:success/:complete/:death)` callbacks, live progress, nested batches, autoflush + linger, nested death cascade, and per-callback rescue.
|
|
37
|
-
|
|
38
|
-
### Limiters
|
|
39
|
-
- Enterprise rate limiters — concurrent, bucket, window, leaky, and points — each exposing a uniform live `#status` (`used`/`limit`/`reset_at`/`available?`); concurrent additionally reports metric counters. Includes a poison-pill brake.
|
|
40
|
-
|
|
41
|
-
### Periodic
|
|
42
|
-
- Cron loops (sidekiq-cron compatible): schedule parsing with timezone/DST handling, leader-gated firing, pause/resume, enqueue-now, and fire history.
|
|
43
|
-
|
|
44
|
-
### Encryption
|
|
45
|
-
- Transparent job-payload encryption with key rotation and graceful failure modes (a decryption failure degrades rather than crashing the worker).
|
|
46
|
-
|
|
47
|
-
### Dashboard
|
|
48
|
-
- Precompiled React + TypeScript SPA mounted under the engine — consumers never run Node. Tabs: queues, retries, scheduled, dead, busy, processes, batches (+ per-batch detail), limiters, periodic, metrics, and search. SSE live updates, read-only mode, pagination, i18n with host-app override, and a dark default theme.
|
|
49
|
-
|
|
50
|
-
### Compat
|
|
51
|
-
- `Sidekiq::*` aliases for every public `Wurk::*` class (`Sidekiq::Worker`, `Sidekiq::Batch`, `Sidekiq::Limiter`, `Sidekiq.configure_server`, …) — the drop-in contract.
|
|
52
|
-
- ActiveJob adapter, `IterableJob`, embedded mode, and a standalone `exe/wurk` runner.
|
|
53
|
-
- Sidekiq client/server middleware contract; third-party ecosystem suites (sidekiq-cron, sidekiq-unique-jobs, sidekiq-scheduler, sidekiq-status, sidekiq-failures, sidekiq-throttled) pass against Wurk.
|
|
54
|
-
|
|
55
|
-
[Unreleased]: https://github.com/developerz-ai/wurk/compare/v0.0.3...HEAD
|
|
56
|
-
[0.0.3]: https://github.com/developerz-ai/wurk/compare/v0.0.2...v0.0.3
|
|
57
|
-
[0.0.2]: https://github.com/developerz-ai/wurk/compare/v0.0.1...v0.0.2
|
|
58
|
-
[0.0.1]: https://github.com/developerz-ai/wurk/releases/tag/v0.0.1
|
data/CONTRIBUTING.md
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
# Contributing to Wurk
|
|
2
|
-
|
|
3
|
-
Thanks for helping make Wurk better. This guide covers local setup, the test
|
|
4
|
-
layers, and the conventions a change has to follow to merge.
|
|
5
|
-
|
|
6
|
-
## Setup
|
|
7
|
-
|
|
8
|
-
```sh
|
|
9
|
-
git clone https://github.com/developerz-ai/wurk
|
|
10
|
-
cd wurk
|
|
11
|
-
bundle install
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
You'll need a local **Redis ≥ 7.0** running (tests use real Redis, never a mock).
|
|
15
|
-
Node is only needed if you touch the dashboard frontend (`frontend/`); the
|
|
16
|
-
precompiled bundle is committed under `vendor/assets/`.
|
|
17
|
-
|
|
18
|
-
## Running the tests
|
|
19
|
-
|
|
20
|
-
| Task | Command |
|
|
21
|
-
|---|---|
|
|
22
|
-
| Full suite (parallel) | `bin/rake test` |
|
|
23
|
-
| A single file | `bin/rake test TEST=test/path/to/file_test.rb` |
|
|
24
|
-
| A single test by name | `bin/rake test TEST=test/foo_test.rb TESTOPTS="--name=/pattern/"` |
|
|
25
|
-
| Parity suite (oracles lifted from Sidekiq) | `bin/rake test:parity` |
|
|
26
|
-
| Ecosystem compatibility | `bin/rake test:ecosystem` |
|
|
27
|
-
| Coverage gate | `COVERAGE=1 bin/rake test` |
|
|
28
|
-
| Benchmarks | `bin/rake bench` |
|
|
29
|
-
| Lint | `bundle exec rubocop` |
|
|
30
|
-
|
|
31
|
-
Test layers:
|
|
32
|
-
|
|
33
|
-
- **unit** — plain Ruby classes in isolation.
|
|
34
|
-
- **engine** — boots the dummy Rails app in `test/dummy/`.
|
|
35
|
-
- **integration** — real forks + real Redis.
|
|
36
|
-
- **parity** (`test/parity/`) — tests lifted from upstream Sidekiq, SHA-pinned.
|
|
37
|
-
These are **oracles**: if Wurk diverges, Wurk is wrong unless the divergence
|
|
38
|
-
is explicitly documented as intentional.
|
|
39
|
-
- **ecosystem** — third-party Sidekiq gem suites run against Wurk.
|
|
40
|
-
|
|
41
|
-
Never mock Redis in integration or parity tests. Each test uses a unique Redis
|
|
42
|
-
key namespace so the parallel runner stays safe.
|
|
43
|
-
|
|
44
|
-
## Conventions
|
|
45
|
-
|
|
46
|
-
These are non-negotiable — they're what keep Wurk a true drop-in:
|
|
47
|
-
|
|
48
|
-
- **Wire-compat is sacred.** Never change a Redis key, JSON field, or
|
|
49
|
-
sorted-set score format. If an optimization would break compatibility, drop
|
|
50
|
-
the optimization.
|
|
51
|
-
- **SOLID, especially SRP.** One reason to change per class — Manager owns
|
|
52
|
-
lifecycle, Fetcher owns the Redis pop, Processor owns middleware + perform,
|
|
53
|
-
Client owns enqueue.
|
|
54
|
-
- **Match the spec.** Any public Sidekiq surface must match
|
|
55
|
-
`docs/target/sidekiq-{free,pro,ent}.md` exactly.
|
|
56
|
-
- **Frozen string literals everywhere**; per-fork Redis pools (never share a
|
|
57
|
-
socket across a fork).
|
|
58
|
-
- **Comments explain non-obvious _why_**, never restate the code.
|
|
59
|
-
- **Coverage**: line coverage on `lib/` must stay ≥ 90% (the gate blocks PRs
|
|
60
|
-
below it). Branch coverage is tracked and ratcheting toward 90%.
|
|
61
|
-
|
|
62
|
-
## Pull requests
|
|
63
|
-
|
|
64
|
-
1. Branch off `main`.
|
|
65
|
-
2. Keep the change focused; add tests at the right layer.
|
|
66
|
-
3. Run `bin/rake test`, `bin/rake test:parity`, `bin/rake test:ecosystem`, and `bundle exec rubocop` locally.
|
|
67
|
-
4. Open the PR — CI runs the matrix (Ruby 3.2/3.3/3.4 × Rails 7.2/8.0), the
|
|
68
|
-
coverage gate, the parity job, and benchmarks. The bench bot comments
|
|
69
|
-
per-benchmark deltas; a real regression fails the check.
|
|
70
|
-
5. Don't `--no-verify` past a failing hook — fix the hook.
|
|
71
|
-
|
|
72
|
-
By contributing you agree your work is licensed under the project's
|
|
73
|
-
[MIT License](LICENSE).
|
data/SECURITY.md
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# Security Policy
|
|
2
|
-
|
|
3
|
-
## Supported versions
|
|
4
|
-
|
|
5
|
-
Wurk follows semantic versioning. Security fixes land on the latest minor
|
|
6
|
-
release line.
|
|
7
|
-
|
|
8
|
-
| Version | Supported |
|
|
9
|
-
|---|---|
|
|
10
|
-
| 1.x | ✅ |
|
|
11
|
-
| < 1.0 | ❌ |
|
|
12
|
-
|
|
13
|
-
## Reporting a vulnerability
|
|
14
|
-
|
|
15
|
-
**Please do not open a public issue for security vulnerabilities.**
|
|
16
|
-
|
|
17
|
-
Report privately through GitHub's
|
|
18
|
-
[**Report a vulnerability**](https://github.com/developerz-ai/wurk/security/advisories/new)
|
|
19
|
-
form (Security → Advisories). This opens a private advisory only the
|
|
20
|
-
maintainers can see.
|
|
21
|
-
|
|
22
|
-
Please include:
|
|
23
|
-
|
|
24
|
-
- a description of the issue and its impact,
|
|
25
|
-
- the affected version(s),
|
|
26
|
-
- steps to reproduce or a proof of concept,
|
|
27
|
-
- any suggested remediation.
|
|
28
|
-
|
|
29
|
-
## What to expect
|
|
30
|
-
|
|
31
|
-
- **Acknowledgement** within 3 business days.
|
|
32
|
-
- An initial assessment and severity within 7 days.
|
|
33
|
-
- Coordinated disclosure: we'll agree on a timeline with you, ship a patched
|
|
34
|
-
release, and credit you in the advisory and `CHANGELOG.md` unless you prefer
|
|
35
|
-
to remain anonymous.
|
|
36
|
-
|
|
37
|
-
Because Wurk is wire-compatible with Sidekiq and runs your job code with access
|
|
38
|
-
to Redis, reports about deserialization, the dashboard's auth surface, or
|
|
39
|
-
argument encryption are especially welcome.
|