String Key Value Blueprint
Store and retrieve arbitrary-length string values with atomic increment, decrement, append, and range operations
| Feature | string-key-value |
| Category | Data |
| Version | 1.0.0 |
| Tags | strings, key-value, atomic-operations, numeric-operations |
| YAML Source | View on GitHub |
| JSON API | string-key-value.json |
Actors
| ID | Name | Type | Description |
|---|---|---|---|
client | Client | human | Application requesting string operations |
Fields
| Name | Type | Required | Label | Description |
|---|---|---|---|---|
key | text | Yes | Key | |
value | text | No | Value | |
ttl_milliseconds | number | No | Ttl Milliseconds | |
is_numeric | boolean | No | Is Numeric | |
old_value | text | No | Old Value | |
encoding | select | No | Encoding |
States
State field: existence
Values:
| State | Initial | Terminal |
|---|---|---|
absent | Yes | |
present | ||
expired | Yes |
Rules
- general: String size cannot exceed 512 MB (configurable via proto_max_bulk_len), Numeric operations (INCR, DECR) require value to be a valid 64-bit signed integer; otherwise fail with syntax error, Increment/decrement values must fit in [-2^63, 2^63-1]; overflow checked and rejected with error, Floating-point increment (INCRBYFLOAT) parsed as long double; operations returning NaN or Infinity fail, APPEND and SETRANGE extend string with zero-padding if needed; SETRANGE with negative offset rejected, All operations are atomic—no partial states visible to concurrent clients, SET with NX (if-not-exists) and XX (if-exists) conditions are mutually exclusive
Outcomes
Read_existing_string (Priority: 1)
Retrieve existing string value
Given:
- key exists and has string value
- key is not expired
Then:
- emit_event event:
string.read
Result: client receives full string value
Read_missing_key (Priority: 2)
Attempt to read non-existent key
Given:
- key does not exist
Then:
- emit_event event:
string.miss
Result: client receives null/nil
Read_with_ttl_modification (Priority: 3)
Read value and optionally modify or check TTL
Given:
- key exists with string value
- GETEX command with optional expiry flags
Then:
- set_field target:
ttl_milliseconds - set_field target:
ttl_millisecondsvalue:null - emit_event event:
string.getex
Result: client receives string value; TTL optionally modified
Set_or_overwrite (Priority: 10)
Set value unconditionally, overwriting if exists
Given:
- SET command issued
Then:
- set_field target:
value— store new value - set_field target:
ttl_millisecondsvalue:null - set_field target:
is_numeric— evaluate if value parseable as integer for optimization - emit_event event:
string.set
Result: key now holds new value; client receives OK
Set_with_conditions (Priority: 11)
SET only if condition met (NX, XX, or equality check)
Given:
condition_type(input) inNX,XX,IFEQ,IFNE,IFDEQ,IFDNEcondition_met(computed) eqtrue
Then:
- set_field target:
value— store new value - emit_event event:
string.set_conditional
Result: value set and OK returned; or nil if condition not met
Set_with_ttl (Priority: 12)
Set value with immediate expiration time
Given:
-
SET with EX PX EXAT PXAT flag
Then:
- set_field target:
value - set_field target:
ttl_milliseconds— calculate absolute expiration time - emit_event event:
string.set_expiring
Result: key set with expiration; expires at specified time
Conditional_set_fails (Priority: 13) — Error: CONDITION_NOT_MET
Given:
-
SET with NX XX IFEQ IFNE condition condition_met(computed) eqfalse
Then:
- emit_event event:
string.set_rejected
Result: value unchanged; client receives nil
Append_to_string (Priority: 20) — Error: STRING_TOO_LARGE
Append suffix to existing or missing string
Given:
- APPEND command
value(input) exists
Then:
- set_field target:
value— concatenate suffix to end - emit_event event:
string.appended
Result: string extended; client receives new total length
Get_substring (Priority: 21)
Extract substring by start/end indices
Given:
- GETRANGE key start end
start(input) gte-2^31end(input) lte2^31-1
Then:
- emit_event event:
string.range_read
Result: substring from start to end inclusive (0-indexed, supports negative indices); empty string if range out of bounds
Set_substring (Priority: 22)
Overwrite portion of string starting at offset
Given:
- SETRANGE key offset value
offset(input) gte0
Then:
- set_field target:
value— overwrite starting at offset; zero-pad if needed - emit_event event:
string.range_written
Result: string modified; client receives new total length
Setrange_with_invalid_offset (Priority: 23) — Error: INVALID_OFFSET
Given:
- SETRANGE with negative offset
Result: error returned; string unchanged
Increment_integer (Priority: 30)
Increment numeric string value by integer amount
Given:
- INCR, INCRBY, or DECR command
value(db) matches^-?[0-9]{1,19}$increment_amount(computed) exists
Then:
- set_field target:
value— increment or decrement value - emit_event event:
string.incr
Result: client receives new numeric value
Increment_non_numeric (Priority: 31) — Error: NOT_AN_INTEGER
Given:
- value is not a valid 64-bit signed integer string
Result: error returned; value unchanged
Increment_overflow (Priority: 32) — Error: INCREMENT_OVERFLOW
Given:
would_overflow(computed) eqtrue
Result: error returned; value unchanged
Increment_float (Priority: 33)
Increment numeric string by floating-point amount
Given:
- INCRBYFLOAT command
value(db) existsresult(computed) not_inNaN,Infinity
Then:
- set_field target:
value— increment by float; store as formatted decimal string - emit_event event:
string.incrbyfloat
Result: client receives new value as decimal string
Increment_float_invalid (Priority: 34) — Error: FLOAT_INVALID
Given:
result(computed) inNaN,Infinity
Result: error returned; value unchanged
Getset_atomically (Priority: 40)
Atomically retrieve old value and set new value
Given:
- GETSET or SET with GET flag
Then:
- emit_event event:
string.getset
Result: old value returned to client; new value now stored
Getdel_atomically (Priority: 41)
Atomically retrieve value and delete key
Given:
- GETDEL command
Then:
- emit_event event:
string.getdel - transition_state field:
existencefrom:presentto:absent
Result: value returned to client; key deleted
Mget_multiple_keys (Priority: 50)
Retrieve multiple values in single request
Given:
- MGET key1 [key2 …]
Then:
- emit_event event:
string.mget
Result: array returned with value for each key (nil for missing or non-string keys)
Mset_multiple_keys (Priority: 51)
Set multiple key-value pairs atomically
Given:
- MSET key1 value1 [key2 value2 …]
Then:
- emit_event event:
string.mset
Result: all keys set; client receives OK
Msetnx_conditional_bulk (Priority: 52)
Set multiple pairs only if ALL keys absent
Given:
- MSETNX key1 value1 [key2 value2 …]
all_keys_absent(db) eqtrue
Then:
- emit_event event:
string.msetnx_success
Result: all keys set; client receives 1
Msetnx_condition_fails (Priority: 53) — Error: KEY_EXISTS
Given:
all_keys_absent(db) eqfalse
Then:
- emit_event event:
string.msetnx_rejected
Result: no keys set; client receives 0
Errors
| Code | Status | Message | Retry |
|---|---|---|---|
NOT_AN_INTEGER | 400 | Value is not an integer or out of range | No |
INCREMENT_OVERFLOW | 400 | Increment or decrement would overflow | No |
CONDITION_NOT_MET | 409 | SET condition not met | No |
INVALID_OFFSET | 400 | Offset is out of range | No |
STRING_TOO_LARGE | 413 | String exceeds maximum allowed size | No |
FLOAT_INVALID | 400 | Float increment resulted in NaN or Infinity | No |
KEY_EXISTS | 409 | One or more keys already exist | No |
Events
| Event | Description | Payload |
|---|---|---|
string.read | ||
string.miss | ||
string.set | ||
string.set_conditional | ||
string.set_expiring | ||
string.appended | ||
string.range_read | ||
string.range_written | ||
string.incr | ||
string.incrbyfloat | ||
string.getset | ||
string.getdel | ||
string.mget | ||
string.mset | ||
string.msetnx_success | ||
string.msetnx_rejected |
Related Blueprints
| Feature | Relationship | Reason |
|---|---|---|
| key-expiration | required | TTL support integrated into string operations |
| multi-exec-transactions | optional | Multiple string commands often wrapped in transactions |
AGI Readiness
Goals
Reliable String Key Value
Store and retrieve arbitrary-length string values with atomic increment, decrement, append, and range operations
Success Metrics:
| Metric | Target | Measurement |
|---|---|---|
| data_accuracy | 100% | Records matching source of truth |
| duplicate_rate | 0% | Duplicate records detected post-creation |
Constraints:
- performance (non-negotiable): Data consistency must be maintained across concurrent operations
Autonomy
Level: supervised
Human Checkpoints:
- before transitioning to a terminal state
Escalation Triggers:
error_rate > 5
Tradeoffs
| Prefer | Over | Reason |
|---|---|---|
| data_integrity | performance | data consistency must be maintained across all operations |
Coordination
Protocol: orchestrated
Consumes:
| Capability | From | Fallback |
|---|---|---|
key_expiration | key-expiration | degrade |
Safety
| Action | Permission | Cooldown | Max Auto |
|---|---|---|---|
| read_existing_string | autonomous | - | - |
| read_missing_key | autonomous | - | - |
| read_with_ttl_modification | supervised | - | - |
| set_or_overwrite | autonomous | - | - |
| set_with_conditions | autonomous | - | - |
| set_with_ttl | autonomous | - | - |
| conditional_set_fails | autonomous | - | - |
| append_to_string | autonomous | - | - |
| get_substring | autonomous | - | - |
| set_substring | autonomous | - | - |
| setrange_with_invalid_offset | autonomous | - | - |
| increment_integer | autonomous | - | - |
| increment_non_numeric | autonomous | - | - |
| increment_overflow | autonomous | - | - |
| increment_float | autonomous | - | - |
| increment_float_invalid | autonomous | - | - |
| getset_atomically | autonomous | - | - |
| getdel_atomically | autonomous | - | - |
| mget_multiple_keys | autonomous | - | - |
| mset_multiple_keys | autonomous | - | - |
| msetnx_conditional_bulk | autonomous | - | - |
| msetnx_condition_fails | autonomous | - | - |