Skip to main content

fast_cache/commands/
pttl.rs

1//! PTTL command parsing and execution.
2
3use crate::Result;
4use crate::protocol::{FastCommand, Frame};
5#[cfg(feature = "server")]
6use crate::server::commands::{BorrowedCommandContext, DirectCommandContext};
7#[cfg(feature = "server")]
8use crate::server::commands::{RawCommandContext, RawDirectCommand};
9#[cfg(feature = "server")]
10use crate::server::wire::ServerWire;
11use crate::storage::{Command, EngineCommandContext, EngineFrameFuture};
12
13use super::parsing::CommandArity;
14use super::{DecodedFastCommand, ttl::Ttl};
15
16pub(crate) struct Pttl;
17pub(crate) static COMMAND: Pttl = Pttl;
18
19#[derive(Debug, Clone)]
20pub(crate) struct OwnedPttl {
21    key: Vec<u8>,
22}
23
24impl OwnedPttl {
25    fn new(key: Vec<u8>) -> Self {
26        Self { key }
27    }
28}
29
30impl super::OwnedCommandData for OwnedPttl {
31    type Spec = Pttl;
32
33    fn route_key(&self) -> Option<&[u8]> {
34        Some(&self.key)
35    }
36
37    fn to_borrowed_command(&self) -> super::BorrowedCommandBox<'_> {
38        Box::new(BorrowedPttl::new(&self.key))
39    }
40}
41
42#[derive(Debug, Clone, Copy)]
43pub(crate) struct BorrowedPttl<'a> {
44    key: &'a [u8],
45}
46
47impl<'a> BorrowedPttl<'a> {
48    fn new(key: &'a [u8]) -> Self {
49        Self { key }
50    }
51}
52
53impl<'a> super::BorrowedCommandData<'a> for BorrowedPttl<'a> {
54    type Spec = Pttl;
55
56    fn route_key(&self) -> Option<&'a [u8]> {
57        Some(self.key)
58    }
59
60    fn to_owned_command(&self) -> Command {
61        Command::new(Box::new(OwnedPttl::new(self.key.to_vec())))
62    }
63
64    fn execute_engine<'b>(&'b self, ctx: EngineCommandContext<'b>) -> EngineFrameFuture<'b>
65    where
66        'a: 'b,
67    {
68        let key = self.key;
69        Box::pin(async move {
70            Ttl::execute_engine_integer(ctx, key, true)
71                .await
72                .map(Frame::Integer)
73        })
74    }
75
76    #[cfg(feature = "server")]
77    fn execute_borrowed_frame(&self, store: &crate::storage::EmbeddedStore, _now_ms: u64) -> Frame {
78        Frame::Integer(store.pttl_millis(self.key))
79    }
80
81    #[cfg(feature = "server")]
82    fn execute_borrowed(&self, ctx: BorrowedCommandContext<'_, '_, '_>) {
83        ServerWire::write_resp_integer(ctx.out, ctx.store.pttl_millis(self.key));
84    }
85
86    #[cfg(feature = "server")]
87    fn execute_direct_borrowed(&self, ctx: DirectCommandContext) -> Frame {
88        Frame::Integer(ctx.ttl(self.key, true))
89    }
90}
91
92impl super::CommandSpec for Pttl {
93    const NAME: &'static str = "PTTL";
94    const MUTATES_VALUE: bool = false;
95}
96
97impl super::OwnedCommandParse for Pttl {
98    fn parse_owned(parts: &[Vec<u8>]) -> Result<Command> {
99        CommandArity::<Self>::exact(parts.len(), 2)?;
100        Ok(Command::new(Box::new(OwnedPttl::new(parts[1].clone()))))
101    }
102}
103
104impl<'a> super::BorrowedCommandParse<'a> for Pttl {
105    fn parse_borrowed(parts: &[&'a [u8]]) -> Result<super::BorrowedCommandBox<'a>> {
106        CommandArity::<Self>::exact(parts.len(), 2)?;
107        Ok(Box::new(BorrowedPttl::new(parts[1])))
108    }
109}
110
111impl DecodedFastCommand for Pttl {
112    fn matches_decoded_fast(&self, _command: &FastCommand<'_>) -> bool {
113        false
114    }
115}
116
117#[cfg(feature = "server")]
118impl RawDirectCommand for Pttl {
119    fn execute(&self, ctx: RawCommandContext<'_, '_, '_>) {
120        match ctx.args.as_slice() {
121            [key] => ServerWire::write_resp_integer(ctx.out, ctx.store.pttl_millis(key)),
122            _ => ServerWire::write_resp_error(
123                ctx.out,
124                "ERR wrong number of arguments for 'PTTL' command",
125            ),
126        }
127    }
128}