Skip to content
axxbetadocs
nextv0.2.26
GitHub
These are the docs of main, not released yet. See the docs of v0.2.26, the latest release.

Seed and check Redis

View .mdOpen in Claude

Services keep what they are asked for often in Redis: a cached view, an idempotency key, a session. The redis pack seeds keys before a scenario acts, and checks what your service wrote, or that it dropped a key it had to drop. It works with every server that speaks Redis’s protocol: Redis itself, Valkey, Dragonfly, KeyDB and Garnet.

Scenario: A scan drops the parcel's cached tracking view
Given a seeds/cache-dropped.yaml db seed
And a redis/tracking-PX-RDS-9603.yaml redis seed
When a message is published to the depots/LEJ/scans mqtt topic:
"""
{"scanId": "SC-9603-1", "parcelRef": "PX-RDS-9603", "status": "OUT_FOR_DELIVERY"}
"""
Then within 20s the tracking:PX-RDS-9603 redis key does not exist

Add the pack to the project with axx pack add redis (Choose packs).

Register the server once, usually in the Background:

Background:
Given the cache redis server with the following properties:
| url | redis://${sys:local.host}:6379/0 |

The url is redis://user:password@host:6379/0, or rediss:// for TLS. A database row picks another database than the URL’s. A password, in the URL or from ${env:..}, is masked in logs and failures.

A seed file maps each key to what it holds, and optionally how long it lasts:

redis/tracking-PX-RDS-9602.yaml
"tracking:PX-RDS-9602":
value: {"parcelRef": "PX-RDS-9602", "status": "OUT_FOR_DELIVERY", "lastLocation": "Leipzig"}
ttl: 10m
"shop:hawthorn-home":
hash: {name: Hawthorn Home, tier: gold}
"depot:LEJ:sorting":
list: [PX-RDS-9601, PX-RDS-9602]
"parcels:express":
set: [PX-RDS-9611, PX-RDS-9612]
"couriers:deliveries":
sorted set: {CR-LEJ-12: 42, CR-LEJ-7: 17}
Given a redis/tracking-PX-RDS-9602.yaml redis seed
  • What a key holds: value is text, or JSON for an object or an array. The other kinds are hash, list, set and sorted set, whose members map to their scores.
  • Replacing: a seed replaces any key of the same name, so a scenario starts from what its seed says.
  • ttl: a duration like 10m, after which the key expires.
Then the idempotency:rowanberry-crafts:order-8812 redis key has the value 'PX-RDS-9604'
And the tracking:PX-RDS-9601 redis key has the following properties:
| parcelRef | PX-RDS-9601 |
| status | REGISTERED |
And within 20s the tracking:PX-RDS-9603 redis key does not exist
  • has the value compares a string key’s text, all of it.

  • has the following properties: reads the key as JSON, whatever its type:

    • a string holding JSON is that JSON;
    • a hash is an object of its fields;
    • a list is an array;
    • a set is a sorted array;
    • a sorted set is an object of its members and their scores.

    Each row is a path into it and the value it has, as in the other JSON property steps: null for null and undefined for absent.

  • does not exist checks that a key is gone, for a service that deletes it or lets it expire.

Every check waits for the key to be as it says: 10 seconds, or the time within gives.

Scenarios run in parallel against the same server, so each seeds and checks keys of its own, named after data unique to it, such as a parcel reference. An axx lint rule can keep seeded key names unique across files:

axx.yaml
lint:
rules:
- name: Redis keys in seeds
filePatterns: ["redis/*.yaml"]
regex: '^"([^"]+)":'
validation: cross-file-unique

See the redis pack’s reference for every step.