Implement a function execute_ttl_cache(operations: list[list[object]]) -> list[list[object]] that simulates a TTL cache. The cache supports put, get, delete, size, and a deterministic fetch operation. fetch does not accept a callable loader; instead, the loader outcome is provided directly in the operation, making every input JSON-serializable and reproducible.
Each operation in operations uses one of these formats:
["put", time_ms, key, value, ttl_ms]["get", time_ms, key]["delete", time_ms, key]["size", time_ms]["fetch", time_ms, key, ttl_ms, loader_status, loader_payload]Keys are strings and cached values are integers. time_ms values are nonnegative integers and appear in nondecreasing order. A record written at time T with a positive ttl_ms is valid only for times strictly less than T + ttl_ms; at or after T + ttl_ms it is expired. A ttl_ms of 0 means the record never expires. Expired records are not removed automatically; they are retained until an explicit delete or replacement, and size counts them.
Return one result per operation, in the same order:
put returns ["ok"]. A put always installs a fresh record for key, discarding any prior stored record, valid or expired.get returns ["ok", value] when the key is stored and valid, otherwise ["ok", null].delete returns ["ok", true] when a stored record exists, even if expired, and removes it; otherwise it returns ["ok", false].size returns ["ok", count], where count includes stored expired records.fetch first checks for a stored, valid entry. If one exists, fetch immediately returns ["ok", value] and ignores the loader fields. If the key is missing or its stored record is expired, the loader fields are consulted. loader_status is either "ok" or "error". On "ok", the cache stores loader_payload under key with the supplied ttl_ms, treating this fetch time as the new write time, and returns ["ok", loader_payload]. On "error", the cache is left unchanged and fetch returns ["error", loader_payload], where loader_payload is the reason string.Malformed input must raise ValueError. This includes unknown operation names, an operation shape that does not match its declared fields, values of incorrect types, a decreasing timestamp, ttl_ms less than zero, loader_status outside "ok" or "error", and loader payload types that do not match the status.
Example 1:
Input:
[
["put", 10, "alpha", 7, 30],
["get", 20, "alpha"],
["get", 40, "alpha"],
["size", 40],
["delete", 50, "alpha"],
["size", 50]
]
Output:
[
["ok"],
["ok", 7],
["ok", null],
["ok", 1],
["ok", true],
["ok", 0]
]
Explanation: alpha is valid at time 20, expires exactly at time 40, remains stored and counted at time 40, then is deleted at time 50.
operations = [["put", 10, "alpha", 7, 30], ["get", 20, "alpha"], ["get", 40, "alpha"], ["size", 40], ["delete", 50, "alpha"], ["size", 50]][["ok"],["ok", 7], ["ok", null], ["ok", 1], ["ok", true], ["ok", 0]]
empty
Six operations arrive in nondecreasing time order; the cache starts empty.
Example 2:
Input:
[
["put", 0, "beta", 3, 10],
["fetch", 5, "beta", 99, "ok", 42],
["get", 5, "beta"],
["fetch", 10, "beta", 20, "error", "timeout"],
["size", 10],
["fetch", 10, "beta", 20, "ok", 55],
["get", 25, "beta"],
["fetch", 30, "gamma", 40, "error", "db_down"],
["size", 30]
]
Output:
[
["ok"],
["ok", 3],
["ok", 3],
["error", "timeout"],
["ok", 1],
["ok", 55],
["ok", 55],
["error", "db_down"],
["ok", 1]
]
Explanation: At time 5 beta is still valid, so the first fetch ignores its loader fields and returns 3. At time 10 the record is expired; a loader error leaves the expired record stored, then a subsequent loader success replaces it. Missing gamma is not stored after its loader error.
Example 3:
Input:
[
["put", 1, "omega", 10, 0],
["get", 999, "omega"],
["put", 1000, "omega", 11, 5],
["size", 1000],
["delete", 1000, "omega"],
["delete", 1001, "omega"]
]
Output:
[
["ok"],
["ok", 10],
["ok"],
["ok", 1],
["ok", true],
["ok", false]
]
Explanation: A zero TTL keeps the original record valid indefinitely. The later put replaces it with a record expiring at time 1005, then the first delete removes that record and the second delete finds nothing.
Constraints:
ttl_ms is a nonnegative integer.loader_payload is an integer for loader_status == "ok" and a string for loader_status == "error".operations = [["put", 10, "alpha", 7, 30], ["get", 20, "alpha"], ["get", 40, "alpha"], ["size", 40], ["delete", 50, "alpha"], ["size", 50]][["ok"],["ok", 7], ["ok", null], ["ok", 1], ["ok", true], ["ok", 0]]
empty
Six operations arrive in nondecreasing time order; the cache starts empty.