Skip to content

Commit a954e1f

Browse files
committed
copy
1 parent 2aa0fe7 commit a954e1f

File tree

2 files changed

+118
-66
lines changed

2 files changed

+118
-66
lines changed

src/RESPite.StackExchange.Redis/RedisCommands.KeyCommands.cs

Lines changed: 112 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Runtime.CompilerServices;
2-
using System.Runtime.InteropServices.ComTypes;
32
using RESPite.Messages;
43
using StackExchange.Redis;
54

@@ -19,6 +18,14 @@ public readonly struct KeyCommands(in RespContext context)
1918

2019
internal static partial class KeyCommandsExtensions
2120
{
21+
[RespCommand(Formatter = "CopyFormatter.Instance")]
22+
public static partial RespOperation<bool> Copy(
23+
this in KeyCommands context,
24+
RedisKey source,
25+
RedisKey destination,
26+
int destinationDatabase = -1,
27+
bool replace = false);
28+
2229
[RespCommand]
2330
public static partial RespOperation<bool> Del(this in KeyCommands context, RedisKey key);
2431

@@ -28,36 +35,9 @@ internal static partial class KeyCommandsExtensions
2835
[RespCommand]
2936
public static partial RespOperation<byte[]?> Dump(this in KeyCommands context, RedisKey key);
3037

31-
[RespCommand("object")]
32-
public static partial RespOperation<string?> ObjectEncoding(this in KeyCommands context, [RespPrefix("ENCODING")] RedisKey key);
33-
34-
[RespCommand("object", Parser = "RespParsers.TimeSpanFromSeconds")]
35-
public static partial RespOperation<TimeSpan?> ObjectIdleTime(this in KeyCommands context, [RespPrefix("IDLETIME")] RedisKey key);
36-
37-
[RespCommand("object")]
38-
public static partial RespOperation<long?> ObjectRefCount(this in KeyCommands context, [RespPrefix("REFCOUNT")] RedisKey key);
39-
40-
[RespCommand("object")]
41-
public static partial RespOperation<long?> ObjectFreq(this in KeyCommands context, [RespPrefix("FREQ")] RedisKey key);
42-
43-
[RespCommand(Parser = "RespParsers.TimeSpanFromSeconds")]
44-
public static partial RespOperation<TimeSpan?> Ttl(this in KeyCommands context, RedisKey key);
45-
46-
[RespCommand(Parser = "RespParsers.TimeSpanFromMilliseconds")]
47-
public static partial RespOperation<TimeSpan?> Pttl(this in KeyCommands context, RedisKey key);
48-
49-
[RespCommand(Parser = "RespParsers.DateTimeFromSeconds")]
50-
public static partial RespOperation<DateTime?> ExpireTime(this in KeyCommands context, RedisKey key);
51-
52-
[RespCommand(Parser = "RespParsers.DateTimeFromMilliseconds")]
53-
public static partial RespOperation<DateTime?> PExpireTime(this in KeyCommands context, RedisKey key);
54-
5538
[RespCommand]
5639
public static partial RespOperation<bool> Exists(this in KeyCommands context, RedisKey key);
5740

58-
[RespCommand]
59-
public static partial RespOperation<bool> Move(this in KeyCommands context, RedisKey key, int db);
60-
6141
[RespCommand]
6242
public static partial RespOperation<long> Exists(this in KeyCommands context, [RespKey] RedisKey[] keys);
6343

@@ -77,6 +57,9 @@ public static RespOperation<bool> Expire(this in KeyCommands context, RedisKey k
7757
return PExpire(context, key, millis, when);
7858
}
7959

60+
[RespCommand(Formatter = "ExpireFormatter.Instance")]
61+
public static partial RespOperation<bool> Expire(this in KeyCommands context, RedisKey key, long seconds, ExpireWhen when = ExpireWhen.Always);
62+
8063
public static RespOperation<bool> ExpireAt(this in KeyCommands context, RedisKey key, DateTime? expiry, ExpireWhen when = ExpireWhen.Always)
8164
{
8265
if (expiry is null || expiry == DateTime.MaxValue)
@@ -93,15 +76,78 @@ public static RespOperation<bool> ExpireAt(this in KeyCommands context, RedisKey
9376
return PExpireAt(context, key, millis, when);
9477
}
9578

79+
[RespCommand(Formatter = "ExpireFormatter.Instance")]
80+
public static partial RespOperation<bool> ExpireAt(this in KeyCommands context, RedisKey key, long seconds, ExpireWhen when = ExpireWhen.Always);
81+
82+
[RespCommand(Parser = "RespParsers.DateTimeFromSeconds")]
83+
public static partial RespOperation<DateTime?> ExpireTime(this in KeyCommands context, RedisKey key);
84+
85+
[RespCommand]
86+
public static partial RespOperation<bool> Move(this in KeyCommands context, RedisKey key, int db);
87+
88+
[RespCommand("object")]
89+
public static partial RespOperation<string?> ObjectEncoding(this in KeyCommands context, [RespPrefix("ENCODING")] RedisKey key);
90+
91+
[RespCommand("object")]
92+
public static partial RespOperation<long?> ObjectFreq(this in KeyCommands context, [RespPrefix("FREQ")] RedisKey key);
93+
94+
[RespCommand("object", Parser = "RespParsers.TimeSpanFromSeconds")]
95+
public static partial RespOperation<TimeSpan?> ObjectIdleTime(this in KeyCommands context, [RespPrefix("IDLETIME")] RedisKey key);
96+
97+
[RespCommand("object")]
98+
public static partial RespOperation<long?> ObjectRefCount(this in KeyCommands context, [RespPrefix("REFCOUNT")] RedisKey key);
99+
100+
[RespCommand(Formatter = "ExpireFormatter.Instance")]
101+
public static partial RespOperation<bool> PExpire(this in KeyCommands context, RedisKey key, long milliseconds, ExpireWhen when = ExpireWhen.Always);
102+
103+
[RespCommand(Formatter = "ExpireFormatter.Instance")]
104+
public static partial RespOperation<bool> PExpireAt(this in KeyCommands context, RedisKey key, long milliseconds, ExpireWhen when = ExpireWhen.Always);
105+
106+
[RespCommand(Parser = "RespParsers.DateTimeFromMilliseconds")]
107+
public static partial RespOperation<DateTime?> PExpireTime(this in KeyCommands context, RedisKey key);
108+
96109
[RespCommand]
97110
public static partial RespOperation<bool> Persist(this in KeyCommands context, RedisKey key);
98111

112+
[RespCommand(Parser = "RespParsers.TimeSpanFromMilliseconds")]
113+
public static partial RespOperation<TimeSpan?> Pttl(this in KeyCommands context, RedisKey key);
114+
115+
[RespCommand]
116+
public static partial RespOperation<RedisKey> RandomKey(this in KeyCommands context);
117+
118+
[RespCommand]
119+
public static partial RespOperation<bool> Rename(this in KeyCommands context, RedisKey key, RedisKey newKey);
120+
121+
[RespCommand]
122+
public static RespOperation<bool> Rename(this in KeyCommands context, RedisKey key, RedisKey newKey, When when)
123+
{
124+
switch (when)
125+
{
126+
case When.Always:
127+
return Rename(context, key, newKey);
128+
case When.NotExists:
129+
return RenameNx(context, key, newKey);
130+
default:
131+
when.AlwaysOrNotExists(); // throws
132+
return default;
133+
}
134+
}
135+
136+
[RespCommand]
137+
public static partial RespOperation<bool> RenameNx(this in KeyCommands context, RedisKey key, RedisKey newKey);
138+
139+
[RespCommand(Formatter = "RestoreFormatter.Instance")]
140+
public static partial RespOperation Restore(this in KeyCommands context, RedisKey key, TimeSpan? ttl, byte[] serializedValue);
141+
99142
[RespCommand]
100143
public static partial RespOperation<bool> Touch(this in KeyCommands context, RedisKey key);
101144

102145
[RespCommand]
103146
public static partial RespOperation<long> Touch(this in KeyCommands context, [RespKey] RedisKey[] keys);
104147

148+
[RespCommand(Parser = "RespParsers.TimeSpanFromSeconds")]
149+
public static partial RespOperation<TimeSpan?> Ttl(this in KeyCommands context, RedisKey key);
150+
105151
[RespCommand(Parser = "RedisTypeParser.Instance")]
106152
public static partial RespOperation<RedisType> Type(this in KeyCommands context, RedisKey key);
107153

@@ -118,51 +164,33 @@ public RedisType Parse(ref RespReader reader)
118164
}
119165
}
120166

121-
[RespCommand]
122-
public static partial RespOperation<bool> Rename(this in KeyCommands context, RedisKey key, RedisKey newKey);
123-
124-
[RespCommand(Formatter = "RestoreFormatter.Instance")]
125-
public static partial RespOperation Restore(this in KeyCommands context, RedisKey key, TimeSpan? ttl, byte[] serializedValue);
126-
127-
private sealed class RestoreFormatter : IRespFormatter<(RedisKey Key, TimeSpan? Ttl, byte[] SerializedValue)>
167+
private sealed class CopyFormatter : IRespFormatter<(RedisKey Source, RedisKey Destination, int DestinationDatabase,
168+
bool Replace)>
128169
{
129-
public static readonly RestoreFormatter Instance = new();
130-
private RestoreFormatter() { }
170+
public static readonly CopyFormatter Instance = new();
171+
private CopyFormatter() { }
131172

132173
public void Format(
133174
scoped ReadOnlySpan<byte> command,
134175
ref RespWriter writer,
135-
in (RedisKey Key, TimeSpan? Ttl, byte[] SerializedValue) request)
176+
in (RedisKey Source, RedisKey Destination, int DestinationDatabase, bool Replace) request)
136177
{
137-
writer.WriteCommand(command, 3);
138-
writer.Write(request.Key);
139-
if (request.Ttl.HasValue)
178+
writer.WriteCommand(command, (request.DestinationDatabase >= 0 ? 4 : 2) + (request.Replace ? 1 : 0));
179+
writer.Write(request.Source);
180+
writer.Write(request.Destination);
181+
if (request.DestinationDatabase >= 0)
140182
{
141-
writer.WriteBulkString((long)request.Ttl.Value.TotalMilliseconds);
183+
writer.WriteRaw("$2\r\nDB\r\n"u8);
184+
writer.WriteBulkString(request.DestinationDatabase);
142185
}
143-
else
186+
187+
if (request.Replace)
144188
{
145-
writer.WriteRaw("$1\r\n0\r\n"u8);
189+
writer.WriteRaw("$7\r\nREPLACE\r\n"u8);
146190
}
147-
writer.WriteBulkString(request.SerializedValue);
148191
}
149192
}
150193

151-
[RespCommand]
152-
public static partial RespOperation<RedisKey> RandomKey(this in KeyCommands context);
153-
154-
[RespCommand(Formatter = "ExpireFormatter.Instance")]
155-
public static partial RespOperation<bool> Expire(this in KeyCommands context, RedisKey key, long seconds, ExpireWhen when = ExpireWhen.Always);
156-
157-
[RespCommand(Formatter = "ExpireFormatter.Instance")]
158-
public static partial RespOperation<bool> PExpire(this in KeyCommands context, RedisKey key, long milliseconds, ExpireWhen when = ExpireWhen.Always);
159-
160-
[RespCommand(Formatter = "ExpireFormatter.Instance")]
161-
public static partial RespOperation<bool> ExpireAt(this in KeyCommands context, RedisKey key, long seconds, ExpireWhen when = ExpireWhen.Always);
162-
163-
[RespCommand(Formatter = "ExpireFormatter.Instance")]
164-
public static partial RespOperation<bool> PExpireAt(this in KeyCommands context, RedisKey key, long milliseconds, ExpireWhen when = ExpireWhen.Always);
165-
166194
private sealed class ExpireFormatter : IRespFormatter<(RedisKey Key, long Value, ExpireWhen When)>
167195
{
168196
public static readonly ExpireFormatter Instance = new();
@@ -199,4 +227,28 @@ public void Format(
199227
}
200228
}
201229
}
230+
231+
private sealed class RestoreFormatter : IRespFormatter<(RedisKey Key, TimeSpan? Ttl, byte[] SerializedValue)>
232+
{
233+
public static readonly RestoreFormatter Instance = new();
234+
private RestoreFormatter() { }
235+
236+
public void Format(
237+
scoped ReadOnlySpan<byte> command,
238+
ref RespWriter writer,
239+
in (RedisKey Key, TimeSpan? Ttl, byte[] SerializedValue) request)
240+
{
241+
writer.WriteCommand(command, 3);
242+
writer.Write(request.Key);
243+
if (request.Ttl.HasValue)
244+
{
245+
writer.WriteBulkString((long)request.Ttl.Value.TotalMilliseconds);
246+
}
247+
else
248+
{
249+
writer.WriteRaw("$1\r\n0\r\n"u8);
250+
}
251+
writer.WriteBulkString(request.SerializedValue);
252+
}
253+
}
202254
}

src/RESPite.StackExchange.Redis/RespContextDatabase.Key.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@ namespace RESPite.StackExchange.Redis;
55

66
internal partial class RespContextDatabase
77
{
8+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
9+
private KeyCommands Keys(CommandFlags flags) => Context(flags).Keys();
10+
811
// Async Key methods
912
public Task<bool> KeyCopyAsync(
1013
RedisKey sourceKey,
1114
RedisKey destinationKey,
1215
int destinationDatabase = -1,
1316
bool replace = false,
14-
CommandFlags flags = CommandFlags.None) =>
15-
throw new NotImplementedException();
16-
17-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
18-
private KeyCommands Keys(CommandFlags flags) => Context(flags).Keys();
17+
CommandFlags flags = CommandFlags.None)
18+
=> Keys(flags).Copy(sourceKey, destinationKey, destinationDatabase, replace).AsTask();
1919

2020
public Task<long> KeyDeleteAsync(RedisKey[] keys, CommandFlags flags = CommandFlags.None)
2121
=> Keys(flags).Del(keys).AsTask();
@@ -78,7 +78,7 @@ public Task<bool> KeyRenameAsync(
7878
RedisKey newKey,
7979
When when = When.Always,
8080
CommandFlags flags = CommandFlags.None)
81-
=> Keys(flags).Rename(key, newKey).AsTask();
81+
=> Keys(flags).Rename(key, newKey, when).AsTask();
8282

8383
public Task KeyRestoreAsync(
8484
RedisKey key,

0 commit comments

Comments
 (0)