Expand description
The keyspace itself: what is there, what type it is, and when it goes away.
Strings and Sets each hold the commands
for one type. The commands here hold for all of them, because a deadline is
not a string thing or a set thing. EXPIRE puts the moment in the key’s own
record, so the same call works on a key holding a string, a set or a hash and
costs the same on each.
use std::time::Duration;
let db = yo::open(yo::MEMORY)?;
let keys = db.keys();
db.set("online").add("alice")?;
keys.expire_in("online", Duration::from_secs(60))?;
assert_eq!(keys.kind("online")?, Some(yo::Kind::Set));
assert!(keys.ttl("online")?.left().is_some());§What a deadline is not
It is not a property of the value. Giving a set a deadline rewrites five
bytes of the key’s record and does not touch a single member, which is why
Keys::expire_in on a set of a million members is the same call as on a
set of one.
It is also not the same as the per field deadlines a hash can carry. Those
are HEXPIRE and they live in the hash. A key can have a deadline while its
fields have their own, and neither one knows about the other.
§The clock is only read when it matters
A database that has never been asked for a deadline never reads the clock on
the data path, which Db::reads_the_clock
reports. The first call here that creates one turns that on for good, so it
is worth knowing that this is where the tens of nanoseconds come from.
§There is no touch
Redis has a TOUCH, and on a real server it counts the keys that are there
and moves each of them up the eviction order. There is no eviction here, so
all it could do is count, and Keys::count already does that. A second
name for one call is worse than no second name, so the wire has TOUCH for
the clients that send it and this does not.
§There is no cursor
The wire has SCAN because a server cannot stop and walk a keyspace for one
client while every other client waits, so it hands out a number and does the
walk in pieces. Nothing here is in that position. Keys::each holds the
database for as long as it runs and nothing else can write to it in the
meantime, so it is one walk, it sees one version of the keyspace, and there
is no cursor to hold and no duplicate to filter out.
What that costs is that a walk of ten million keys is ten million calls
before the next line of your program runs. That is the same trade KEYS
makes and it is the right one here, because the thing on the other side of
the call is your own code rather than a socket.
§The typed collections are somewhere else
A Map is a named collection and not a key in the keyspace, so
it does not show up here and cannot be given a deadline. That is 15
section 3’s split and not an oversight: a map’s name is checked when it is
opened, and a key’s name is whatever you pass.
Structs§
- Keys
- Every command that works on a key whatever the key holds.