Dragonfly exposes absolute key expiration times
Dragonfly 1.22 adds EXPIRETIME and PEXPIRETIME and fixes absolute timestamps in the Memcached interface. Search introspection and a larger compatibility suite address other details applications depend on.
A remaining lifetime and an expiration timestamp answer different questions. A duration describes how long a key has left at the instant of observation. An absolute timestamp identifies the deadline itself. Dragonfly's EXPIRETIME and PEXPIRETIME implementation adds the second form of inspection, including explicit results for keys that are absent or have no deadline.
The commands arrive in Dragonfly 1.22.0, published on September 3. The release also corrects absolute expiration handling in the Memcached interface, adds FT.TAGVALS, and incorporates a large compatibility test contribution. These changes concern the detailed meaning of existing application operations, including their units and boundary cases.
I find this kind of compatibility work relevant to Dragonfly's appeal as a larger single-process cache. Reusing a protocol can reduce adoption work, but the application still depends on the values returned by introspection commands. A deadline with the wrong interpretation can be more damaging than an explicit unsupported-command error.
Expiration inspection preserves exceptional states
The new command's tests first query an absent key and expect -2 from both commands. After creating the key without an expiry, they expect -1. These values distinguish absence from indefinite retention, so a caller does not need to treat every nonpositive response as the same state.
The test then assigns an absolute millisecond expiry using PEXPIREAT. It expects PEXPIRETIME to report that millisecond deadline and EXPIRETIME to return its seconds representation. This gives applications a way to inspect the deadline already stored by the engine, rather than calculating one by adding a newly observed duration to a client clock.
SET inspection-example value
EXPIRETIME inspection-example
PEXPIRETIME inspection-example
Both inspection commands return -1 in this sequence because no expiry was assigned. If the key does not exist, the tests establish the separate -2 result. The distinction belongs to the command's result contract and should survive any conversion into an application's own optional or nullable representation.
Absolute inspection is useful when the deadline itself is part of the application's reasoning. Two observations of a remaining lifetime can differ simply because time has passed between them. A reported deadline instead identifies the configured target time. That does not remove clock-related questions across systems, but it avoids manufacturing a new deadline from a duration sampled at a different instant.
Memcached uses one field for two time representations
The Memcached expiration correction handles a protocol convention in which the expiration field can represent either a duration or an absolute Unix timestamp. The code uses a threshold of thirty days. Nonzero values at or below that threshold are relative seconds, while larger values are timestamps.
The dispatch path now converts relative values into absolute time and sends the resulting expiry through the internal EXAT option. Absolute timestamps pass through as timestamps. Previously, treating the value as a relative duration could misinterpret a normal Unix timestamp as an extremely long lifetime. The patch makes the conversion explicit at the protocol boundary.
Its regression test stores one item with a relative lifetime and another with an absolute deadline a short time ahead. Both remain readable initially and disappear after their deadlines. A third item starts with a later timestamp and then receives a timestamp in the past. The test expects the third item to disappear after that update.
The past-timestamp behaviour requires a related correction to SET. The source explains that applying an already expired timestamp to an existing key must remove that key. Returning a successful store response while leaving the old value available would not implement the requested state. The fix runs deletion for that case before returning the response.
I regard these changes as more consequential than their small command-parsing footprint suggests. The relative and absolute forms share one input field, so ordinary application configuration determines which branch runs. Correct interpretation allows the same client convention to retain its meaning when the server engine changes.
Value metadata has a width and a serialized form
The release's Memcached flags correction changes the flag representation to uint32_t and adds serialization and deserialization. This addresses both the range of values represented and their passage through storage or transfer code. Preserving a value's bytes is insufficient if the flags attached by the client change along the way.
This is a separate issue from expiration, even though both accompany stored values in the Memcached interface. One concerns time interpretation, and the other concerns metadata representation. The fixes illustrate why a compatible storage command has to preserve the complete request's meaning through internal formats, not merely accept its payload.
Tag enumeration adds index introspection
The FT.TAGVALS tests query a tag field containing repeated colour values and expect the distinct values red, blue, and green. The command provides an index-level view of the tag vocabulary. An application does not have to retrieve every matching document merely to discover which tag values the index holds.
The tests separately reject an unknown index, an unknown field, and a field that exists but is numeric. These cases matter to callers building schema-driven interfaces. An empty vocabulary and an invalid field selection should not collapse into the same successful result. The command requires a tag field, not just any field in a valid index.
The test also documents a discrepancy in aliased-field handling. Dragonfly accepts the original name when a field has an alias, while the comment identifies a different behaviour in Redis Stack. The release therefore adds useful introspection without establishing identical behaviour for every naming case.
Compatibility tests expand the set of observable differences
The fakeredis-based test contribution brings broader command-compatibility checks into the project. Its author explicitly notes tests marked unsupported for Dragonfly even though they should pass in the author's judgement. The contribution supplies more executable expectations while also recording unresolved cases.
That is a more informative reading than treating a larger suite as proof of complete compatibility. Tests make discrepancies reproducible and help associate fixes with specific behaviours. In this release, the expiration commands, timestamp conversion, and tag enumeration each have concrete assertions. Their value lies in defining what an application can observe, including absence, expired values, and invalid schema requests.