Repository navigation
fix: L1-only mode (backend=None) should not attempt Redis connection - #6
Merged
Merged
Conversation
When using @cache(backend=None) for L1-only caching, the decorator was still attempting to connect to Redis on every operation. Root cause: Sentinel problem - couldn't distinguish explicit backend=None from unspecified backend. Changes: - Track explicit backend=None intent via _l1_only_mode flag - Skip backend provider lookup in L1-only mode - Fix invalidate_cache() to honor L1-only mode - Add DEBUG log when L1-only mode ignores available Redis - Clean up ttl or ttl copy-paste cruft Closes #3
… level Remove buggy check that treated DecoratorConfig.backend defaulting to None as L1-only mode. Now only @cache(backend=None) triggers L1-only. For L1-only with presets, use: @cache(backend=None, config=...)
Adds TestDefaultBackendBehavior class with 6 tests verifying that: - @cache() without backend=None DOES call get_backend_provider() - @cache.minimal/dev/test() presets behave correctly - DecoratorConfig default (backend=None) != explicit backend=None - Explicit backend instances bypass provider lookup These regression tests protect against the bug where checking `config.backend is None` would treat ALL decorators as L1-only (since DecoratorConfig.backend defaults to None).
27Bslash6
force-pushed
the
fix/l1-only-mode-no-redis
branch
from
December 11, 2025 21:55
47f3b46 to
872fe23
Compare
27Bslash6
added a commit
that referenced
this pull request
Sep 1, 2026
…LAB-1149) (#263) * fix(fuzz): commit per-target corpus seeds cargo-fuzz actually loads (LAB-1149) The fuzz corpus was buried by three stacked defects: the gitignore pattern corpus/*/ excluded every seed the generator produced; the committed CORPUS_INFO.md documented 1,758 seeds (6.9MB, 2025-11) that were not in the repo; and the generator wrote a category tree (byte_storage/, encryption/) that no [[bin]] target name matches, so cargo-fuzz could never have loaded those seeds even if committed. Every run cold-started from random bytes. - generate_corpus.sh: rewritten to write deterministic seeds into corpus/<target>/ for all 14 targets, shaped per target input format. StorageEnvelope seeds are byte-exact against cachekit-core 0.4.0's wire format (raw LZ4 block, xxHash3-64 big-endian checksum, rmp-serde array form), verified against the crate's pinned empty-input checksum vector. - .gitignore: corpus is no longer ignored; comment states the actual policy. - CORPUS_INFO.md: describes the real tree; no volatile counts (live numbers come from validate_corpus.sh). - validate_corpus.sh: derives targets from Cargo.toml [[bin]] stanzas and FAILS when any target has no seeds or the corpus exceeds the 10MB budget. - minimize_corpus.sh: target list derived from Cargo.toml instead of a hand-maintained copy; a failed cmin now fails the script. - README.md: corpus sections match the per-target layout; stale Blake3 and FUZZ_TARGETS-list references corrected. - .pre-commit-config.yaml: corpus excluded from trailing-whitespace and end-of-file-fixer - appending a newline to a seed silently changes it. No CI change needed: cargo fuzz run defaults its corpus to fuzz/corpus/ <target>, so fuzz-smoke.yml and security-deep.yml pick the seeds up as-is. Measured (60s, nightly-2026-04-27, -print_final_stats=1): - encryption_large_payload cold: cov 185, ft 194, max input len 53 bytes after 5,376 execs. Seeded (5 files found): ft 300, 256KB inputs from exec #6 - the target finally tests large payloads. - byte_storage_decompress cold: cov 2156, ft 3492. Seeded (14 files found): cov 2420, ft 4110 - valid-checksum envelopes unlock the post-decompression verify branches. * fix(fuzz): apply expert-panel findings to corpus tooling (LAB-1149) Panel: bug-hunter-supreme, security-specialist, code-craftsman, catchphrase-agent (high stakes). Security: no findings. Applied: - fuzz-smoke.yml: validate corpus layout before the build - without this step the every-target-has-seeds guarantee was manual-only, and a target added tomorrow would fuzz cold forever behind a green badge. The step can only fail loudly; no existing guarantee weakened. - validate_corpus.sh: assert grep-derived target count matches fuzz_targets/*.rs (a [[bin]] stanza whose name line drifts from the grep pattern would silently stop requiring seeds); drop dead .gitkeep filters, the 8MB soft tier, and the --help block. - minimize_corpus.sh: reject unknown target names (a typo'd target previously printed 'Skipping' and exited 0); --help before env checks; drop the duplicate 10MB check (validate_corpus.sh is the single budget enforcer) and dead .gitkeep filters. - rust/fuzz/Makefile: fail quick/deep when FUZZ_TARGETS derives empty - a zero-target loop reported '✓ No crashes found' having fuzzed nothing. - README.md: fix Quick Start commands (make fuzz-* lives at the repo root, not rust/Makefile); delete the AFL++ section and multi-engine claims (no afl feature, no fuzz-afl target - doc fiction); honest large-payload numbers; corpus section now points at CORPUS_INFO.md instead of duplicating it. - generate_corpus.sh: drop 10 filler seeds (key-derivation content variants the target already hard-loops every exec, redundant large-payload sizes, trivial invalid-msgpack bytes) - 72 seeds, 696K total. Re-measured with the final corpus (60s, nightly-2026-04-27): - encryption_large_payload cold: cov 185, ft 194, lim 53b, 5,553 execs. Seeded (3 files): ft 300, 256KB inputs. - byte_storage_decompress cold: cov 2358, ft 3770. Seeded (13 files): cov 2423, ft 3968. * fix: address coderabbit review — corpus tooling correctness (LAB-1149) Parity check (Kody medium + CodeRabbit): the old check compared a count of Cargo.toml [[bin]] names against a count of every *.rs in fuzz_targets/. That was both too strict and too loose — a shared helper module in that directory failed the whole CI step unconditionally, while a duplicated or misspelled name kept the counts equal and slipped through. Neither bot's suggested name-set comparison fixes the helper-module case, so the check now asserts the invariant the comment actually claimed: every [[bin]] stanza must yield exactly one name (stanza count == derived name count), names must be unique, and each must have a fuzz_targets/<name>.rs source. Extra .rs files are now tolerated. minimize_corpus.sh: mapfile is bash 4+, so the script died immediately on stock macOS bash 3.2 — replaced with a portable read loop. `cargo fuzz cmin` needed +nightly like every other cargo-fuzz call in the Makefile; it failed outright on a stable default toolchain. SC2155 split on all four locals. generate_corpus.sh: regeneration was not idempotent — a renamed or dropped seed left its old file committed forever, invisible to a validator that checks presence and size but not provenance. First write per target now clears the *.bin names the script owns, leaving libFuzzer's extensionless hash-named discoveries and committed crash reproducers untouched. The byte-identical claim is scoped to a pinned dependency set (msgpack 1.2.1, lz4 4.4.5, xxhash 4.0.0 — verified to reproduce corpus/ with a clean git status), since the LZ4 block format constrains decoding, not encoder match-finding. fuzz-smoke.yml: corpus validation moved ahead of the toolchain install. It is pure bash over files present at checkout, so a missing seed directory now fails in seconds instead of after ~12 min of rustup + cargo-fuzz install. Makefile: the byte-identical zero-target guard in quick and deep extracted into a require_targets define, matching the file's existing require_binary / warn_if_missing idiom. Docs: MD040 fence language and the missing working directory in CORPUS_INFO.md (its commands resolve from rust/fuzz/, one level up from the file); non-copy-pasteable `make fuzz-*` and `make quick|target|deep|coverage` forms in README.md replaced with the real goal names; MD022/MD031 blank lines added at the three flagged sections. Verified: shellcheck clean on all three scripts; 8/8 checks in a throwaway harness covering each parity failure mode, the helper-module regression, seed orphan removal, discovery preservation, and byte-identical regeneration. Rejected, with reasons on the PR: Kody's print-vs-logging rule (fires on a progress line in an inline heredoc in a one-shot generator whose entire interface is stdout) and CodeRabbit's request to extract the target-derivation grep into a shared helper (the expert panel already rejected this; the fragility it cites is now detected loudly rather than silent). CodeRabbit-Resolved: rust/fuzz/scripts/validate_corpus.sh:43:Compare target na CodeRabbit-Resolved: rust/fuzz/scripts/validate_corpus.sh:31:One fragile targe CodeRabbit-Resolved: rust/fuzz/scripts/minimize_corpus.sh:36:mapfile requires CodeRabbit-Resolved: rust/fuzz/scripts/minimize_corpus.sh:54:Split the local d CodeRabbit-Resolved: rust/fuzz/scripts/minimize_corpus.sh:71:Run corpus minimi CodeRabbit-Resolved: rust/fuzz/scripts/generate_corpus.sh:62:Generation does n CodeRabbit-Resolved: rust/fuzz/scripts/generate_corpus.sh:15:Pin the corpus-ge CodeRabbit-Resolved: .github/workflows/fuzz-smoke.yml:71:Move the corpus valid CodeRabbit-Resolved: rust/fuzz/corpus/CORPUS_INFO.md:9:Add a language to the f CodeRabbit-Resolved: rust/fuzz/Makefile:71:Extract the duplicated zero-target CodeRabbit-Resolved: rust/fuzz/README.md:25:Make these commands copy-paste saf CodeRabbit-Resolved: rust/fuzz/README.md:118:Add the blank lines required by m * fix: address coderabbit review — working-dir docs + parity-filter coherence (LAB-1149) Round 3. CodeRabbit: the README's uv one-liner invoked scripts/generate_corpus.sh from the repo root where that path does not resolve, and CORPUS_INFO.md said 'run from rust/fuzz/' above blocks whose first line is 'cd rust/fuzz' (only correct from the root). One convention now, both files: commands run from the repository root and the cd is part of the recipe. fuzz-smoke.yml source-parity check: filter SRC_COUNT to files containing fuzz_target!. validate_corpus.sh (previous commit) deliberately tolerates a shared helper module in fuzz_targets/, but the workflow's unfiltered *.rs count would fail the job on the same tree that just passed validation — 12 minutes after the fast-fail step, with a misleading 'add the missing stanza' error. The filtered count still catches the real drift (a fuzz_target! source with no [[bin]] stanza). Kody's base-image-digest rule fired on CORPUS_INFO.md line 19 — a markdown doc with no container images; rejected on the thread. CodeRabbit-Resolved: rust/fuzz/README.md:121:working-directory consistency CodeRabbit-Resolved: rust/fuzz/corpus/CORPUS_INFO.md:18:working-directory --------- Co-authored-by: Mark S <ray.geo30@insighttimer.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #3
When using
@cache(backend=None)for L1-only caching, the decorator was still attempting to connect to Redis on every operation.Root Cause
Sentinel problem - couldn't distinguish explicit
backend=Nonefrom unspecified backend.Changes
backend=Noneintent via_l1_only_modeflag inintent.pywrapper.pyinvalidate_cache()andainvalidate_cache()to honor L1-only modettl or ttlcopy-paste cruft (8 instances)Test Plan
tests/unit/test_l1_only_mode.py(10 tests)invalidate_cache()in L1-only modeFiles Changed
src/cachekit/decorators/intent.py- Track explicit L1-only intentsrc/cachekit/decorators/wrapper.py- Honor L1-only flag, add DEBUG logtests/unit/test_l1_only_mode.py- New comprehensive test suite