specbandit 1.1.1 → 1.2.0
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 +3 -2
- data/lib/specbandit/redis_queue.rb +6 -0
- data/lib/specbandit/version.rb +1 -1
- data/lib/specbandit/worker.rb +12 -10
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 24148d640548adc9f3bd6714ad39f4bfd380eeaf8e904f0fffd4b777a9b13d4c
|
|
4
|
+
data.tar.gz: '082673e08f9b40e9c8babae73f658d91b7627a40002b1e326d62fb49c5242d4f'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 06ced4b5b9530b9f836d90a0e05a663acf88d16f008c6f181acc19a1711ee6260465f42b7e27c76d3e16ec8d28ae621bfd4a614d2ec2aae26312927cb40fd3fb
|
|
7
|
+
data.tar.gz: 6f1578c3db2a446bce8677d16020014e4fa1c30e2483789f41311c1d18ba75567875a65728fca9f48136951b722b91631d674e995d2a66b1ebe26b99b910e128
|
data/README.md
CHANGED
|
@@ -319,7 +319,7 @@ The full decision table:
|
|
|
319
319
|
| Yes | Drained / empty | Empty | **OK, exit 0.** Worker arriving late -- everything was already taken by peers and this runner has no re-run memory. |
|
|
320
320
|
| Yes | Has data | Empty | **Steal.** Classic run: pop batches from the shared queue (and record them to the rerun key if one is configured). |
|
|
321
321
|
| Yes | Drained / empty | Has data | **Replay.** Classic re-run: ignore the shared queue and re-run exactly the recorded files. |
|
|
322
|
-
| Yes | Has data | Has data | **
|
|
322
|
+
| Yes | Has data | Has data | **Full rerun.** The queue was re-pushed while this runner still holds rerun memory from a previous run. The stale rerun key is deleted and the runner steals from the shared queue like a classic run, re-recording as it goes. |
|
|
323
323
|
|
|
324
324
|
> **Empty key names count as "not provided".** A `--key-rerun` whose value is an empty string -- e.g. `--key-rerun "$VAR"` where `$VAR` is unset in CI -- is treated exactly like `--key-rerun` being absent. The same applies to `--key-failed`: an empty/unset name is treated as "not configured" and no failed files are recorded.
|
|
325
325
|
|
|
@@ -351,7 +351,7 @@ The full decision table:
|
|
|
351
351
|
|
|
352
352
|
Key details:
|
|
353
353
|
|
|
354
|
-
- **Replay reads non-destructively** (`LRANGE`, not `LPOP`).
|
|
354
|
+
- **Replay reads non-destructively** (`LRANGE`, not `LPOP`). Replay never consumes the rerun key, so re-running the same runner multiple times replays the same files every time. The one case where the rerun key is deleted (`DEL`) is a **full rerun** -- the shared queue has data again while the rerun key still holds files from a previous run -- where the stale memory is reset and rebuilt from the newly stolen batches.
|
|
355
355
|
- **The shared queue is never touched in replay mode**. Other runners are unaffected.
|
|
356
356
|
- **Each runner has its own rerun key**. Only the re-run runner enters replay mode; runners that aren't re-run don't start at all.
|
|
357
357
|
|
|
@@ -429,6 +429,7 @@ specbandit push --key "pr-42-run-100" --key-ttl 259200 --pattern 'spec/**/*_spec
|
|
|
429
429
|
- **Steal** uses `LPOP key count` (Redis 6.2+), which atomically pops up to N elements. No Lua scripts, no locks, no race conditions.
|
|
430
430
|
- **Record** (when `--key-rerun` is set): after each steal, the batch is also `RPUSH`ed to the per-runner rerun key.
|
|
431
431
|
- **Replay** (when the rerun key has data and the shared queue is drained): reads all files from the rerun key via `LRANGE` (non-destructive), splits into batches, and runs them locally. The shared queue is never touched.
|
|
432
|
+
- **Full rerun** (when both the shared queue and the rerun key have data): the stale rerun key is removed with `DEL`, then the runner steals from the shared queue and re-records as in a classic run.
|
|
432
433
|
- **Mode selection** is derived entirely from Redis (published marker + queue/rerun state) -- see the decision table above. There is no re-run flag or environment variable.
|
|
433
434
|
- **Run** delegates to the configured adapter:
|
|
434
435
|
- **CLI adapter**: spawns a shell command per batch via `Open3`, appending file paths as arguments. Works with any test runner.
|
|
@@ -88,6 +88,12 @@ module Specbandit
|
|
|
88
88
|
with_retries { redis.lrange(key, 0, -1) }
|
|
89
89
|
end
|
|
90
90
|
|
|
91
|
+
# Remove a key entirely. Used to discard stale rerun memory when a
|
|
92
|
+
# full rerun starts over from the shared queue.
|
|
93
|
+
def delete(key)
|
|
94
|
+
with_retries { redis.del(key) }
|
|
95
|
+
end
|
|
96
|
+
|
|
91
97
|
def close
|
|
92
98
|
redis.close
|
|
93
99
|
end
|
data/lib/specbandit/version.rb
CHANGED
data/lib/specbandit/worker.rb
CHANGED
|
@@ -76,7 +76,7 @@ module Specbandit
|
|
|
76
76
|
# Yes | empty/drained | empty | OK: worker arriving late (0)
|
|
77
77
|
# Yes | has data | empty | Steal (record if rerun key set)
|
|
78
78
|
# Yes | empty/drained | has data | Replay recorded files
|
|
79
|
-
# Yes | has data | has data |
|
|
79
|
+
# Yes | has data | has data | Full rerun: reset rerun key, steal
|
|
80
80
|
#
|
|
81
81
|
# "Published" is a durable marker written by `specbandit push`; it is the
|
|
82
82
|
# only reliable signal that work was ever enqueued, because Redis
|
|
@@ -89,7 +89,7 @@ module Specbandit
|
|
|
89
89
|
rerun_files = key_present?(key_rerun) ? queue.read_all(key_rerun) : []
|
|
90
90
|
|
|
91
91
|
if key_has_data && rerun_files.any?
|
|
92
|
-
|
|
92
|
+
run_full_rerun
|
|
93
93
|
elsif rerun_files.any?
|
|
94
94
|
run_replay(rerun_files)
|
|
95
95
|
elsif key_has_data
|
|
@@ -119,14 +119,16 @@ module Specbandit
|
|
|
119
119
|
1
|
|
120
120
|
end
|
|
121
121
|
|
|
122
|
-
# Both the shared queue and this runner's rerun key hold files
|
|
123
|
-
#
|
|
124
|
-
#
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
output.puts
|
|
129
|
-
|
|
122
|
+
# Both the shared queue and this runner's rerun key hold files: the queue
|
|
123
|
+
# was re-pushed while this runner still carries rerun memory from a
|
|
124
|
+
# previous run (a full rerun). The stored memory is stale -- discard it
|
|
125
|
+
# and steal from the shared queue like a classic run, re-recording each
|
|
126
|
+
# stolen batch as we go.
|
|
127
|
+
def run_full_rerun
|
|
128
|
+
output.puts "[specbandit] Shared queue '#{key}' and rerun key '#{key_rerun}' both have files. " \
|
|
129
|
+
"Full rerun: resetting '#{key_rerun}' and working from '#{key}'."
|
|
130
|
+
queue.delete(key_rerun)
|
|
131
|
+
run_steal(record: true)
|
|
130
132
|
end
|
|
131
133
|
|
|
132
134
|
# Replay mode: run a known list of files in local batches.
|