(
cmd: &RespCommand,
session: &RespSession,
state: &SharedState,
is_pttl: bool,
)
| 192 | } |
| 193 | |
| 194 | async fn handle_ttl( |
| 195 | cmd: &RespCommand, |
| 196 | session: &RespSession, |
| 197 | state: &SharedState, |
| 198 | is_pttl: bool, |
| 199 | ) -> RespValue { |
| 200 | let Some(key) = cmd.arg(0) else { |
| 201 | let name = if is_pttl { "pttl" } else { "ttl" }; |
| 202 | return RespValue::err(format!( |
| 203 | "ERR wrong number of arguments for '{name}' command" |
| 204 | )); |
| 205 | }; |
| 206 | |
| 207 | let plan = PhysicalPlan::Kv(KvOp::GetTtl { |
| 208 | collection: session.collection.clone(), |
| 209 | key: key.to_vec(), |
| 210 | }); |
| 211 | |
| 212 | match dispatch_kv(state, session, plan).await { |
| 213 | Ok(resp) if resp.status == Status::Ok => { |
| 214 | let ttl_ms = parse_json_field_i64(&resp.payload, "ttl_ms").unwrap_or(-2); |
| 215 | if ttl_ms < 0 { |
| 216 | // -1 (no TTL) or -2 (not found) — same for both TTL and PTTL. |
| 217 | RespValue::integer(ttl_ms) |
| 218 | } else if is_pttl { |
| 219 | RespValue::integer(ttl_ms) |
| 220 | } else { |
| 221 | // TTL returns seconds, round up to avoid reporting 0 for sub-second TTLs. |
| 222 | RespValue::integer((ttl_ms + 999) / 1000) |
| 223 | } |
| 224 | } |
| 225 | Ok(_) => RespValue::integer(-2), |
| 226 | Err(e) => RespValue::err(format!("ERR {e}")), |
| 227 | } |
| 228 | } |
| 229 | |
| 230 | async fn handle_persist( |
| 231 | cmd: &RespCommand, |
no test coverage detected