未验证 提交 fc43d270 编写于 作者: A Anatoly Sergeev 提交者: GitHub

add resp command in order to distinguish resp types (#763)

上级 f863f6c7
......@@ -31,7 +31,7 @@ final case class ClusterExecutor(
scope: Scope.Closeable
) extends RedisExecutor {
def execute(command: Chunk[RespValue.BulkString]): IO[RedisError, RespValue] = {
def execute(command: RespCommand): IO[RedisError, RespValue] = {
def execute(keySlot: Slot) =
for {
......@@ -58,7 +58,7 @@ final case class ClusterExecutor(
}
for {
key <- ZIO.attempt(command(1)).orElseFail(CusterKeyError)
key <- ZIO.attempt(command.args(1).value).orElseFail(CusterKeyError)
keySlot = Slot((key.asCRC16 % SlotsAmount).toLong)
result <- executeSafe(keySlot)
} yield result
......
......@@ -17,7 +17,6 @@
package zio.redis
import zio._
import zio.redis.RespValue.BulkString
import zio.schema.Schema
import zio.schema.codec.BinaryCodec
......@@ -27,10 +26,10 @@ import java.util.concurrent.TimeUnit
sealed trait Input[-A] {
self =>
private[redis] def encode(data: A)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString]
private[redis] def encode(data: A)(implicit codec: BinaryCodec): RespCommand
final def contramap[B](f: B => A): Input[B] = new Input[B] {
def encode(data: B)(implicit codec: BinaryCodec): Chunk[BulkString] = self.encode(f(data))
def encode(data: B)(implicit codec: BinaryCodec): RespCommand = self.encode(f(data))
}
}
......@@ -38,417 +37,466 @@ object Input {
def apply[A](implicit input: Input[A]): Input[A] = input
@inline
private[this] def encodeString(s: String): RespValue.BulkString = RespValue.bulkString(s)
@inline
private[this] def encodeBytes[A](value: A)(implicit codec: BinaryCodec, schema: Schema[A]): RespValue.BulkString =
RespValue.BulkString(codec.encode(schema)(value))
case object AbsTtlInput extends Input[AbsTtl] {
def encode(data: AbsTtl)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: AbsTtl)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(data.stringify))
}
case object AddressInput extends Input[Address] {
def encode(data: Address)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: Address)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Unknown(data.stringify))
}
case object AggregateInput extends Input[Aggregate] {
def encode(data: Aggregate)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("AGGREGATE"), encodeString(data.stringify))
def encode(data: Aggregate)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal("AGGREGATE"), RespArgument.Literal(data.stringify))
}
case object AlphaInput extends Input[Alpha] {
def encode(data: Alpha)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: Alpha)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(data.stringify))
}
case object AuthInput extends Input[Auth] {
def encode(data: Auth)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("AUTH"), encodeString(data.password))
def encode(data: Auth)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal("AUTH"), RespArgument.Value(data.password))
}
case object BoolInput extends Input[Boolean] {
def encode(data: Boolean)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(if (data) "1" else "0"))
def encode(data: Boolean)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(if (data) "1" else "0"))
}
case object StralgoLcsQueryTypeInput extends Input[StrAlgoLcsQueryType] {
def encode(data: StrAlgoLcsQueryType)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] = data match {
case StrAlgoLcsQueryType.Len => Chunk.single(encodeString("LEN"))
def encode(data: StrAlgoLcsQueryType)(implicit codec: BinaryCodec): RespCommand = data match {
case StrAlgoLcsQueryType.Len => RespCommand(RespArgument.Literal("LEN"))
case StrAlgoLcsQueryType.Idx(minMatchLength, withMatchLength) => {
val idx = Chunk.single(encodeString("IDX"))
val idx = Chunk.single(RespArgument.Literal("IDX"))
val min =
if (minMatchLength > 1) Chunk(encodeString("MINMATCHLEN"), encodeString(minMatchLength.toString))
else Chunk.empty
val length = if (withMatchLength) Chunk.single(encodeString("WITHMATCHLEN")) else Chunk.empty
Chunk(idx, min, length).flatten
if (minMatchLength > 1)
Chunk(RespArgument.Literal("MINMATCHLEN"), RespArgument.Unknown(minMatchLength.toString))
else Chunk.empty[RespArgument]
val length =
if (withMatchLength) Chunk.single(RespArgument.Literal("WITHMATCHLEN")) else Chunk.empty[RespArgument]
RespCommand(Chunk(idx, min, length).flatten)
}
}
}
case object BitFieldCommandInput extends Input[BitFieldCommand] {
def encode(data: BitFieldCommand)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] = {
def encode(data: BitFieldCommand)(implicit codec: BinaryCodec): RespCommand = {
import BitFieldCommand._
data match {
case BitFieldGet(t, o) => Chunk(encodeString("GET"), encodeString(t.stringify), encodeString(o.toString))
val respArgs = data match {
case BitFieldGet(t, o) =>
Chunk(RespArgument.Literal("GET"), RespArgument.Unknown(t.stringify), RespArgument.Unknown(o.toString))
case BitFieldSet(t, o, v) =>
Chunk(encodeString("SET"), encodeString(t.stringify), encodeString(o.toString), encodeString(v.toString))
Chunk(
RespArgument.Literal("SET"),
RespArgument.Unknown(t.stringify),
RespArgument.Unknown(o.toString),
RespArgument.Unknown(v.toString)
)
case BitFieldIncr(t, o, i) =>
Chunk(encodeString("INCRBY"), encodeString(t.stringify), encodeString(o.toString), encodeString(i.toString))
case bfo: BitFieldOverflow => Chunk(encodeString("OVERFLOW"), encodeString(bfo.stringify))
Chunk(
RespArgument.Literal("INCRBY"),
RespArgument.Unknown(t.stringify),
RespArgument.Unknown(o.toString),
RespArgument.Unknown(i.toString)
)
case bfo: BitFieldOverflow => Chunk(RespArgument.Literal("OVERFLOW"), RespArgument.Literal(bfo.stringify))
}
RespCommand(respArgs)
}
}
case object BitOperationInput extends Input[BitOperation] {
def encode(data: BitOperation)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: BitOperation)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(data.stringify))
}
case object BitPosRangeInput extends Input[BitPosRange] {
def encode(data: BitPosRange)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] = {
val start = encodeString(data.start.toString)
data.end.fold(Chunk.single(start))(end => Chunk(start, encodeString(end.toString)))
def encode(data: BitPosRange)(implicit codec: BinaryCodec): RespCommand = {
val start = RespArgument.Unknown(data.start.toString)
val respArgs = data.end.fold(Chunk.single(start))(end => Chunk(start, RespArgument.Unknown(end.toString)))
RespCommand(respArgs)
}
}
case object ByInput extends Input[String] {
def encode(data: String)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("BY"), encodeString(data))
def encode(data: String)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal("BY"), RespArgument.Unknown(data))
}
case object ChangedInput extends Input[Changed] {
def encode(data: Changed)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: Changed)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(data.stringify))
}
case object ClientKillInput extends Input[ClientKillFilter] {
def encode(data: ClientKillFilter)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] = data match {
case addr: ClientKillFilter.Address => Chunk(encodeString("ADDR"), encodeString(addr.stringify))
case laddr: ClientKillFilter.LocalAddress => Chunk(encodeString("LADDR"), encodeString(laddr.stringify))
case ClientKillFilter.Id(clientId) => Chunk(encodeString("ID"), encodeString(clientId.toString))
case ClientKillFilter.Type(clientType) => Chunk(encodeString("TYPE"), encodeString(clientType.stringify))
case ClientKillFilter.User(username) => Chunk(encodeString("USER"), encodeString(username))
case ClientKillFilter.SkipMe(skip) => Chunk(encodeString("SKIPME"), encodeString(if (skip) "YES" else "NO"))
def encode(data: ClientKillFilter)(implicit codec: BinaryCodec): RespCommand = data match {
case addr: ClientKillFilter.Address =>
RespCommand(RespArgument.Literal("ADDR"), RespArgument.Unknown(addr.stringify))
case laddr: ClientKillFilter.LocalAddress =>
RespCommand(RespArgument.Literal("LADDR"), RespArgument.Unknown(laddr.stringify))
case ClientKillFilter.Id(clientId) =>
RespCommand(RespArgument.Literal("ID"), RespArgument.Unknown(clientId.toString))
case ClientKillFilter.Type(clientType) =>
RespCommand(RespArgument.Literal("TYPE"), RespArgument.Literal(clientType.stringify))
case ClientKillFilter.User(username) => RespCommand(RespArgument.Literal("USER"), RespArgument.Unknown(username))
case ClientKillFilter.SkipMe(skip) =>
RespCommand(RespArgument.Literal("SKIPME"), RespArgument.Literal(if (skip) "YES" else "NO"))
}
}
case object ClientPauseModeInput extends Input[ClientPauseMode] {
def encode(data: ClientPauseMode)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: ClientPauseMode)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(data.stringify))
}
case object ClientTrackingInput
extends Input[Option[(Option[Long], Option[ClientTrackingMode], Boolean, Chunk[String])]] {
def encode(
data: Option[(Option[Long], Option[ClientTrackingMode], Boolean, Chunk[String])]
)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
)(implicit codec: BinaryCodec): RespCommand =
data match {
case Some((clientRedir, mode, noLoop, prefixes)) =>
val modeChunk = mode match {
case Some(ClientTrackingMode.OptIn) => Chunk(encodeString("OPTIN"))
case Some(ClientTrackingMode.OptOut) => Chunk(encodeString("OPTOUT"))
case Some(ClientTrackingMode.Broadcast) => Chunk(encodeString("BCAST"))
case None => Chunk.empty
case Some(ClientTrackingMode.OptIn) => RespCommand(RespArgument.Literal("OPTIN"))
case Some(ClientTrackingMode.OptOut) => RespCommand(RespArgument.Literal("OPTOUT"))
case Some(ClientTrackingMode.Broadcast) => RespCommand(RespArgument.Literal("BCAST"))
case None => RespCommand.empty
}
val loopChunk = if (noLoop) Chunk(encodeString("NOLOOP")) else Chunk.empty
Chunk(encodeString("ON")) ++
clientRedir.fold(Chunk.empty: Chunk[RespValue.BulkString])(id =>
Chunk(encodeString("REDIRECT"), encodeString(id.toString))
val loopChunk = if (noLoop) RespCommand(RespArgument.Literal("NOLOOP")) else RespCommand.empty
RespCommand(RespArgument.Literal("ON")) ++
clientRedir.fold(RespCommand.empty)(id =>
RespCommand(RespArgument.Literal("REDIRECT"), RespArgument.Unknown(id.toString))
) ++
RespCommand(
prefixes.flatMap(prefix => Chunk(RespArgument.Literal("PREFIX"), RespArgument.Unknown(prefix)))
) ++
prefixes.flatMap(prefix => Chunk(encodeString("PREFIX"), encodeString(prefix))) ++
modeChunk ++
loopChunk
case None =>
Chunk(encodeString("OFF"))
RespCommand(RespArgument.Literal("OFF"))
}
}
case object CopyInput extends Input[Copy] {
def encode(data: Copy)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: Copy)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(data.stringify))
}
case object CountInput extends Input[Count] {
def encode(data: Count)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("COUNT"), encodeString(data.count.toString))
def encode(data: Count)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal("COUNT"), RespArgument.Unknown(data.count.toString))
}
case object RedisTypeInput extends Input[RedisType] {
def encode(data: RedisType)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("TYPE"), encodeString(data.stringify))
def encode(data: RedisType)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal("TYPE"), RespArgument.Literal(data.stringify))
}
case object PatternInput extends Input[Pattern] {
def encode(data: Pattern)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("MATCH"), encodeString(data.pattern))
def encode(data: Pattern)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal("MATCH"), RespArgument.Unknown(data.pattern))
}
case object GetInput extends Input[String] {
def encode(data: String)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("GET"), encodeString(data))
def encode(data: String)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal("GET"), RespArgument.Unknown(data))
}
case object PositionInput extends Input[Position] {
def encode(data: Position)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: Position)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(data.stringify))
}
case object SideInput extends Input[Side] {
def encode(data: Side)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: Side)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(data.stringify))
}
case object DoubleInput extends Input[Double] {
def encode(data: Double)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.toString))
def encode(data: Double)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Unknown(data.toString))
}
case object DurationMillisecondsInput extends Input[Duration] {
def encode(data: Duration)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.toMillis.toString))
def encode(data: Duration)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Unknown(data.toMillis.toString))
}
case object DurationSecondsInput extends Input[Duration] {
def encode(data: Duration)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] = {
def encode(data: Duration)(implicit codec: BinaryCodec): RespCommand = {
val seconds = TimeUnit.MILLISECONDS.toSeconds(data.toMillis)
Chunk.single(encodeString(seconds.toString))
RespCommand(RespArgument.Unknown(seconds.toString))
}
}
case object DurationTtlInput extends Input[Duration] {
def encode(data: Duration)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] = {
def encode(data: Duration)(implicit codec: BinaryCodec): RespCommand = {
val milliseconds = data.toMillis
Chunk(encodeString("PX"), encodeString(milliseconds.toString))
RespCommand(RespArgument.Literal("PX"), RespArgument.Unknown(milliseconds.toString))
}
}
case object FreqInput extends Input[Freq] {
def encode(data: Freq)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("FREQ"), encodeString(data.frequency))
def encode(data: Freq)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal("FREQ"), RespArgument.Unknown(data.frequency))
}
case object IdleTimeInput extends Input[IdleTime] {
def encode(data: IdleTime)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("IDLETIME"), encodeString(data.seconds.toString))
def encode(data: IdleTime)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal("IDLETIME"), RespArgument.Unknown(data.seconds.toString))
}
case object IncrementInput extends Input[Increment] {
def encode(data: Increment)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: Increment)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(data.stringify))
}
case object KeepTtlInput extends Input[KeepTtl] {
def encode(data: KeepTtl)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: KeepTtl)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(data.stringify))
}
case object LimitInput extends Input[Limit] {
def encode(data: Limit)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("LIMIT"), encodeString(data.offset.toString), encodeString(data.count.toString))
def encode(data: Limit)(implicit codec: BinaryCodec): RespCommand =
RespCommand(
RespArgument.Literal("LIMIT"),
RespArgument.Unknown(data.offset.toString),
RespArgument.Unknown(data.count.toString)
)
}
case object LongInput extends Input[Long] {
def encode(data: Long)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.toString))
def encode(data: Long)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Unknown(data.toString))
}
case object LongLatInput extends Input[LongLat] {
def encode(data: LongLat)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString(data.longitude.toString), encodeString(data.latitude.toString))
def encode(data: LongLat)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Unknown(data.longitude.toString), RespArgument.Unknown(data.latitude.toString))
}
final case class MemberScoreInput[M: Schema]() extends Input[MemberScore[M]] {
def encode(data: MemberScore[M])(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString(data.score.toString), encodeBytes(data.member))
def encode(data: MemberScore[M])(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Unknown(data.score.toString), RespArgument.Value(data.member))
}
case object NoInput extends Input[Unit] {
def encode(data: Unit)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] = Chunk.empty
def encode(data: Unit)(implicit codec: BinaryCodec): RespCommand = RespCommand.empty
}
final case class NonEmptyList[-A](input: Input[A]) extends Input[(A, List[A])] {
def encode(data: (A, List[A]))(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
(data._1 :: data._2).foldLeft(Chunk.empty: Chunk[RespValue.BulkString])((acc, a) => acc ++ input.encode(a))
def encode(data: (A, List[A]))(implicit codec: BinaryCodec): RespCommand =
(data._1 :: data._2).foldLeft(RespCommand.empty)((acc, a) => acc ++ input.encode(a))
}
case object OrderInput extends Input[Order] {
def encode(data: Order)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: Order)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Unknown(data.stringify))
}
case object RadiusUnitInput extends Input[RadiusUnit] {
def encode(data: RadiusUnit)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: RadiusUnit)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Unknown(data.stringify))
}
case object RangeInput extends Input[Range] {
def encode(data: Range)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString(data.start.toString), encodeString(data.end.toString))
def encode(data: Range)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Unknown(data.start.toString), RespArgument.Unknown(data.end.toString))
}
case object ReplaceInput extends Input[Replace] {
def encode(data: Replace)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: Replace)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(data.stringify))
}
case object StoreDistInput extends Input[StoreDist] {
def encode(data: StoreDist)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("STOREDIST"), encodeString(data.key))
def encode(data: StoreDist)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal("STOREDIST"), RespArgument.Unknown(data.key))
}
case object StoreInput extends Input[Store] {
def encode(data: Store)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("STORE"), encodeString(data.key))
def encode(data: Store)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal("STORE"), RespArgument.Unknown(data.key))
}
case object StringInput extends Input[String] {
def encode(data: String)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data))
def encode(data: String)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Unknown(data))
}
case object CommandNameInput extends Input[String] {
def encode(data: String)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.CommandName(data))
}
final case class ArbitraryInput[A: Schema]() extends Input[A] {
def encode(data: A)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeBytes(data))
final case class ArbitraryValueInput[A: Schema]() extends Input[A] {
def encode(data: A)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Value(data))
}
case object ByteInput extends Input[Chunk[Byte]] {
def encode(data: Chunk[Byte])(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(RespValue.BulkString(data))
final case class ArbitraryKeyInput[A: Schema]() extends Input[A] {
def encode(data: A)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Key(data))
}
case object ValueInput extends Input[Chunk[Byte]] {
def encode(data: Chunk[Byte])(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Value(data))
}
final case class OptionalInput[-A](a: Input[A]) extends Input[Option[A]] {
def encode(data: Option[A])(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
data.fold(Chunk.empty: Chunk[RespValue.BulkString])(a.encode)
def encode(data: Option[A])(implicit codec: BinaryCodec): RespCommand =
data.fold(RespCommand.empty)(a.encode)
}
case object TimeSecondsInput extends Input[Instant] {
def encode(data: Instant)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.getEpochSecond.toString))
def encode(data: Instant)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Unknown(data.getEpochSecond.toString))
}
case object TimeMillisecondsInput extends Input[Instant] {
def encode(data: Instant)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.toEpochMilli.toString))
def encode(data: Instant)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Unknown(data.toEpochMilli.toString))
}
case object WeightsInput extends Input[::[Double]] {
def encode(data: ::[Double])(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
data.foldLeft(Chunk.single(encodeString("WEIGHTS")): Chunk[RespValue.BulkString])((acc, a) =>
acc ++ Chunk.single(encodeString(a.toString))
)
def encode(data: ::[Double])(implicit codec: BinaryCodec): RespCommand = {
val args = data.foldLeft(Chunk.single[RespArgument](RespArgument.Literal("WEIGHTS"))) { (acc, a) =>
acc ++ Chunk.single(RespArgument.Unknown(a.toString))
}
RespCommand(args)
}
}
case object IdleInput extends Input[Duration] {
def encode(data: Duration)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("IDLE"), encodeString(data.toMillis.toString))
def encode(data: Duration)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal("IDLE"), RespArgument.Unknown(data.toMillis.toString))
}
case object TimeInput extends Input[Duration] {
def encode(data: Duration)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("TIME"), encodeString(data.toMillis.toString))
def encode(data: Duration)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal("TIME"), RespArgument.Unknown(data.toMillis.toString))
}
case object RetryCountInput extends Input[Long] {
def encode(data: Long)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("RETRYCOUNT"), encodeString(data.toString))
def encode(data: Long)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal("RETRYCOUNT"), RespArgument.Unknown(data.toString))
}
final case class XGroupCreateInput[K: Schema, G: Schema, I: Schema]() extends Input[XGroupCommand.Create[K, G, I]] {
def encode(data: XGroupCommand.Create[K, G, I])(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] = {
val chunk = Chunk(encodeString("CREATE"), encodeBytes(data.key), encodeBytes(data.group), encodeBytes(data.id))
def encode(data: XGroupCommand.Create[K, G, I])(implicit codec: BinaryCodec): RespCommand = {
val chunk = Chunk(
RespArgument.Literal("CREATE"),
RespArgument.Key(data.key),
RespArgument.Unknown(data.group),
RespArgument.Unknown(data.id)
)
if (data.mkStream) chunk :+ encodeString(MkStream.stringify)
else chunk
RespCommand(if (data.mkStream) chunk :+ RespArgument.Literal(MkStream.stringify) else chunk)
}
}
final case class XGroupSetIdInput[K: Schema, G: Schema, I: Schema]() extends Input[XGroupCommand.SetId[K, G, I]] {
def encode(data: XGroupCommand.SetId[K, G, I])(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("SETID"), encodeBytes(data.key), encodeBytes(data.group), encodeBytes(data.id))
def encode(data: XGroupCommand.SetId[K, G, I])(implicit codec: BinaryCodec): RespCommand =
RespCommand(
RespArgument.Literal("SETID"),
RespArgument.Key(data.key),
RespArgument.Unknown(data.group),
RespArgument.Unknown(data.id)
)
}
final case class XGroupDestroyInput[K: Schema, G: Schema]() extends Input[XGroupCommand.Destroy[K, G]] {
def encode(data: XGroupCommand.Destroy[K, G])(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("DESTROY"), encodeBytes(data.key), encodeBytes(data.group))
def encode(data: XGroupCommand.Destroy[K, G])(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal("DESTROY"), RespArgument.Key(data.key), RespArgument.Unknown(data.group))
}
final case class XGroupCreateConsumerInput[K: Schema, G: Schema, C: Schema]()
extends Input[XGroupCommand.CreateConsumer[K, G, C]] {
def encode(data: XGroupCommand.CreateConsumer[K, G, C])(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("CREATECONSUMER"), encodeBytes(data.key), encodeBytes(data.group), encodeBytes(data.consumer))
def encode(data: XGroupCommand.CreateConsumer[K, G, C])(implicit codec: BinaryCodec): RespCommand =
RespCommand(
RespArgument.Literal("CREATECONSUMER"),
RespArgument.Key(data.key),
RespArgument.Unknown(data.group),
RespArgument.Unknown(data.consumer)
)
}
final case class XGroupDelConsumerInput[K: Schema, G: Schema, C: Schema]()
extends Input[XGroupCommand.DelConsumer[K, G, C]] {
def encode(data: XGroupCommand.DelConsumer[K, G, C])(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("DELCONSUMER"), encodeBytes(data.key), encodeBytes(data.group), encodeBytes(data.consumer))
def encode(data: XGroupCommand.DelConsumer[K, G, C])(implicit codec: BinaryCodec): RespCommand =
RespCommand(
RespArgument.Literal("DELCONSUMER"),
RespArgument.Key(data.key),
RespArgument.Unknown(data.group),
RespArgument.Unknown(data.consumer)
)
}
case object BlockInput extends Input[Duration] {
def encode(data: Duration)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("BLOCK"), encodeString(data.toMillis.toString))
def encode(data: Duration)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal("BLOCK"), RespArgument.Unknown(data.toMillis.toString))
}
final case class StreamsInput[K: Schema, V: Schema]() extends Input[((K, V), Chunk[(K, V)])] {
def encode(data: ((K, V), Chunk[(K, V)]))(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] = {
def encode(data: ((K, V), Chunk[(K, V)]))(implicit codec: BinaryCodec): RespCommand = {
val (keys, ids) = (data._1 +: data._2).map { case (key, value) =>
(encodeBytes(key), encodeBytes(value))
(RespArgument.Key(key), RespArgument.Value(value))
}.unzip
Chunk.single(encodeString("STREAMS")) ++ keys ++ ids
RespCommand(Chunk.single(RespArgument.Literal("STREAMS")) ++ keys ++ ids)
}
}
case object NoAckInput extends Input[NoAck] {
def encode(data: NoAck)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: NoAck)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Unknown(data.stringify))
}
case object StreamMaxLenInput extends Input[StreamMaxLen] {
def encode(data: StreamMaxLen)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] = {
def encode(data: StreamMaxLen)(implicit codec: BinaryCodec): RespCommand = {
val chunk =
if (data.approximate)
Chunk(encodeString("MAXLEN"), encodeString("~"))
else
Chunk.single(encodeString("MAXLEN"))
if (data.approximate) Chunk(RespArgument.Literal("MAXLEN"), RespArgument.Literal("~"))
else Chunk.single(RespArgument.Literal("MAXLEN"))
chunk :+ encodeString(data.count.toString)
RespCommand(chunk :+ RespArgument.Unknown(data.count.toString))
}
}
case object ListMaxLenInput extends Input[ListMaxLen] {
def encode(data: ListMaxLen)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("MAXLEN"), encodeString(data.count.toString))
def encode(data: ListMaxLen)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal("MAXLEN"), RespArgument.Unknown(data.count.toString))
}
case object RankInput extends Input[Rank] {
def encode(data: Rank)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("RANK"), encodeString(data.rank.toString))
def encode(data: Rank)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal("RANK"), RespArgument.Unknown(data.rank.toString))
}
final case class Tuple2[-A, -B](_1: Input[A], _2: Input[B]) extends Input[(A, B)] {
def encode(data: (A, B))(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
def encode(data: (A, B))(implicit codec: BinaryCodec): RespCommand =
_1.encode(data._1) ++ _2.encode(data._2)
}
final case class Tuple3[-A, -B, -C](_1: Input[A], _2: Input[B], _3: Input[C]) extends Input[(A, B, C)] {
def encode(data: (A, B, C))(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
def encode(data: (A, B, C))(implicit codec: BinaryCodec): RespCommand =
_1.encode(data._1) ++ _2.encode(data._2) ++ _3.encode(data._3)
}
final case class Tuple4[-A, -B, -C, -D](_1: Input[A], _2: Input[B], _3: Input[C], _4: Input[D])
extends Input[(A, B, C, D)] {
def encode(data: (A, B, C, D))(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
def encode(data: (A, B, C, D))(implicit codec: BinaryCodec): RespCommand =
_1.encode(data._1) ++ _2.encode(data._2) ++ _3.encode(data._3) ++ _4.encode(data._4)
}
final case class Tuple5[-A, -B, -C, -D, -E](_1: Input[A], _2: Input[B], _3: Input[C], _4: Input[D], _5: Input[E])
extends Input[(A, B, C, D, E)] {
def encode(data: (A, B, C, D, E))(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
def encode(data: (A, B, C, D, E))(implicit codec: BinaryCodec): RespCommand =
_1.encode(data._1) ++ _2.encode(data._2) ++ _3.encode(data._3) ++ _4.encode(data._4) ++ _5.encode(data._5)
}
......@@ -460,7 +508,7 @@ object Input {
_5: Input[E],
_6: Input[F]
) extends Input[(A, B, C, D, E, F)] {
def encode(data: (A, B, C, D, E, F))(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
def encode(data: (A, B, C, D, E, F))(implicit codec: BinaryCodec): RespCommand =
_1.encode(data._1) ++ _2.encode(data._2) ++ _3.encode(data._3) ++ _4.encode(data._4) ++ _5.encode(data._5) ++
_6.encode(data._6)
}
......@@ -474,7 +522,7 @@ object Input {
_6: Input[F],
_7: Input[G]
) extends Input[(A, B, C, D, E, F, G)] {
def encode(data: (A, B, C, D, E, F, G))(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
def encode(data: (A, B, C, D, E, F, G))(implicit codec: BinaryCodec): RespCommand =
_1.encode(data._1) ++ _2.encode(data._2) ++ _3.encode(data._3) ++ _4.encode(data._4) ++ _5.encode(data._5) ++
_6.encode(data._6) ++ _7.encode(data._7)
}
......@@ -490,7 +538,7 @@ object Input {
_8: Input[H],
_9: Input[I]
) extends Input[(A, B, C, D, E, F, G, H, I)] {
def encode(data: (A, B, C, D, E, F, G, H, I))(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
def encode(data: (A, B, C, D, E, F, G, H, I))(implicit codec: BinaryCodec): RespCommand =
_1.encode(data._1) ++ _2.encode(data._2) ++ _3.encode(data._3) ++ _4.encode(data._4) ++ _5.encode(data._5) ++
_6.encode(data._6) ++ _7.encode(data._7) ++ _8.encode(data._8) ++ _9.encode(data._9)
}
......@@ -507,7 +555,7 @@ object Input {
_9: Input[I],
_10: Input[J]
) extends Input[(A, B, C, D, E, F, G, H, I, J)] {
def encode(data: (A, B, C, D, E, F, G, H, I, J))(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
def encode(data: (A, B, C, D, E, F, G, H, I, J))(implicit codec: BinaryCodec): RespCommand =
_1.encode(data._1) ++ _2.encode(data._2) ++ _3.encode(data._3) ++ _4.encode(data._4) ++
_5.encode(data._5) ++ _6.encode(data._6) ++ _7.encode(data._7) ++ _8.encode(data._8) ++
_9.encode(data._9) ++ _10.encode(data._10)
......@@ -526,114 +574,116 @@ object Input {
_10: Input[J],
_11: Input[K]
) extends Input[(A, B, C, D, E, F, G, H, I, J, K)] {
def encode(data: (A, B, C, D, E, F, G, H, I, J, K))(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
def encode(data: (A, B, C, D, E, F, G, H, I, J, K))(implicit codec: BinaryCodec): RespCommand =
_1.encode(data._1) ++ _2.encode(data._2) ++ _3.encode(data._3) ++ _4.encode(data._4) ++
_5.encode(data._5) ++ _6.encode(data._6) ++ _7.encode(data._7) ++ _8.encode(data._8) ++
_9.encode(data._9) ++ _10.encode(data._10) ++ _11.encode(data._11)
}
case object UpdateInput extends Input[Update] {
def encode(data: Update)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: Update)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Unknown(data.stringify))
}
final case class GetExPersistInput[K: Schema]() extends Input[(K, Boolean)] {
def encode(data: (K, Boolean))(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
if (data._2) Chunk(encodeBytes(data._1), encodeString("PERSIST")) else Chunk(encodeBytes(data._1))
def encode(data: (K, Boolean))(implicit codec: BinaryCodec): RespCommand =
RespCommand(
if (data._2) Chunk(RespArgument.Key(data._1), RespArgument.Literal("PERSIST"))
else Chunk(RespArgument.Key(data._1))
)
}
final case class GetExInput[K: Schema]() extends Input[(K, Expire, Duration)] {
def encode(
data: (K, Expire, Duration)
)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
def encode(data: (K, Expire, Duration))(implicit codec: BinaryCodec): RespCommand =
data match {
case (key, Expire.SetExpireSeconds, duration) =>
Chunk(encodeBytes(key), encodeString("EX")) ++ DurationSecondsInput.encode(duration)
RespCommand(RespArgument.Key(key), RespArgument.Literal("EX")) ++ DurationSecondsInput.encode(duration)
case (key, Expire.SetExpireMilliseconds, duration) =>
Chunk(encodeBytes(key), encodeString("PX")) ++ DurationMillisecondsInput.encode(duration)
case _ => Chunk(encodeBytes(data._1))
RespCommand(RespArgument.Key(key), RespArgument.Literal("PX")) ++ DurationMillisecondsInput.encode(duration)
}
}
final case class GetExAtInput[K: Schema]() extends Input[(K, ExpiredAt, Instant)] {
def encode(
data: (K, ExpiredAt, Instant)
)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
def encode(data: (K, ExpiredAt, Instant))(implicit codec: BinaryCodec): RespCommand =
data match {
case (key, ExpiredAt.SetExpireAtSeconds, instant) =>
Chunk(encodeBytes(key), encodeString("EXAT")) ++ TimeSecondsInput.encode(instant)
RespCommand(RespArgument.Key(key), RespArgument.Literal("EXAT")) ++ TimeSecondsInput.encode(instant)
case (key, ExpiredAt.SetExpireAtMilliseconds, instant) =>
Chunk(encodeBytes(key), encodeString("PXAT")) ++ TimeMillisecondsInput.encode(instant)
case _ => Chunk(encodeBytes(data._1))
RespCommand(RespArgument.Key(key), RespArgument.Literal("PXAT")) ++ TimeMillisecondsInput.encode(instant)
}
}
case object IdInput extends Input[Long] {
def encode(data: Long)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk(encodeString("ID"), encodeString(data.toString))
def encode(data: Long)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal("ID"), RespArgument.Unknown(data.toString))
}
case object UnblockBehaviorInput extends Input[UnblockBehavior] {
def encode(data: UnblockBehavior)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: UnblockBehavior)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Unknown(data.stringify))
}
final case class Varargs[-A](input: Input[A]) extends Input[Iterable[A]] {
def encode(data: Iterable[A])(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
data.foldLeft(Chunk.empty: Chunk[RespValue.BulkString])((acc, a) => acc ++ input.encode(a))
def encode(data: Iterable[A])(implicit codec: BinaryCodec): RespCommand =
data.foldLeft(RespCommand.empty)((acc, a) => acc ++ input.encode(a))
}
final case class EvalInput[-K, -V](inputK: Input[K], inputV: Input[V]) extends Input[(String, Chunk[K], Chunk[V])] {
def encode(data: (String, Chunk[K], Chunk[V]))(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] = {
def encode(data: (String, Chunk[K], Chunk[V]))(implicit codec: BinaryCodec): RespCommand = {
val (lua, keys, args) = data
val encodedScript = Chunk(encodeString(lua), encodeString(keys.size.toString))
val encodedKeys = keys.flatMap(inputK.encode)
val encodedArgs = args.flatMap(inputV.encode)
val encodedScript = RespCommand(RespArgument.Unknown(lua), RespArgument.Unknown(keys.size.toString))
val encodedKeys = keys.foldLeft(RespCommand.empty)((acc, a) =>
acc ++ inputK.encode(a).mapArguments(arg => RespArgument.Key(arg.value.value))
)
val encodedArgs = args.foldLeft(RespCommand.empty)((acc, a) =>
acc ++ inputV.encode(a).mapArguments(arg => RespArgument.Value(arg.value.value))
)
encodedScript ++ encodedKeys ++ encodedArgs
}
}
case object ScriptDebugInput extends Input[DebugMode] {
def encode(data: DebugMode)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: DebugMode)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(data.stringify))
}
case object ScriptFlushInput extends Input[FlushMode] {
def encode(data: FlushMode)(implicit codec: BinaryCodec): Chunk[BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: FlushMode)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(data.stringify))
}
case object WithScoresInput extends Input[WithScores] {
def encode(data: WithScores)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: WithScores)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(data.stringify))
}
case object WithCoordInput extends Input[WithCoord] {
def encode(data: WithCoord)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: WithCoord)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(data.stringify))
}
case object WithDistInput extends Input[WithDist] {
def encode(data: WithDist)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: WithDist)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(data.stringify))
}
case object WithHashInput extends Input[WithHash] {
def encode(data: WithHash)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: WithHash)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(data.stringify))
}
case object WithForceInput extends Input[WithForce] {
def encode(data: WithForce)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: WithForce)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(data.stringify))
}
case object WithJustIdInput extends Input[WithJustId] {
def encode(data: WithJustId)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(data.stringify))
def encode(data: WithJustId)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(data.stringify))
}
case object YesNoInput extends Input[Boolean] {
def encode(data: Boolean)(implicit codec: BinaryCodec): Chunk[RespValue.BulkString] =
Chunk.single(encodeString(if (data) "YES" else "NO"))
def encode(data: Boolean)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal(if (data) "YES" else "NO"))
}
}
......@@ -17,7 +17,7 @@
package zio.redis
import zio._
import zio.redis.Input.{StringInput, Varargs}
import zio.redis.Input.{CommandNameInput, Varargs}
import zio.schema.codec.BinaryCodec
final class RedisCommand[-In, +Out] private (
......@@ -34,8 +34,8 @@ final class RedisCommand[-In, +Out] private (
.flatMap[Any, Throwable, Out](out => ZIO.attempt(output.unsafeDecode(out)(codec)))
.refineToOrDie[RedisError]
private[redis] def resp(in: In): Chunk[RespValue.BulkString] =
Varargs(StringInput).encode(name.split(" "))(codec) ++ input.encode(in)(codec)
private[redis] def resp(in: In): RespCommand =
Varargs(CommandNameInput).encode(name.split(" "))(codec) ++ input.encode(in)(codec)
}
object RedisCommand {
......
......@@ -16,10 +16,10 @@
package zio.redis
import zio.{Chunk, IO, ZLayer}
import zio.{IO, ZLayer}
trait RedisExecutor {
def execute(command: Chunk[RespValue.BulkString]): IO[RedisError, RespValue]
def execute(command: RespCommand): IO[RedisError, RespValue]
}
object RedisExecutor {
......
/*
* Copyright 2021 John A. De Goes and the ZIO contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package zio.redis
import zio.Chunk
import zio.redis.RespValue.BulkString
import zio.schema.Schema
import zio.schema.codec.BinaryCodec
import java.nio.charset.StandardCharsets
sealed trait RespArgument {
def value: RespValue.BulkString
}
object RespArgument {
final case class Unknown(bytes: Chunk[Byte]) extends RespArgument {
lazy val value: BulkString = RespValue.BulkString(bytes)
}
object Unknown {
def apply(str: String): Unknown = Unknown(Chunk.fromArray(str.getBytes(StandardCharsets.UTF_8)))
def apply[A](data: A)(implicit codec: BinaryCodec, schema: Schema[A]): Unknown = Unknown(codec.encode(schema)(data))
}
final case class CommandName(str: String) extends RespArgument {
lazy val value: BulkString = RespValue.bulkString(str)
}
final case class Literal(str: String) extends RespArgument {
lazy val value: BulkString = RespValue.bulkString(str)
}
final case class Key(bytes: Chunk[Byte]) extends RespArgument {
lazy val value: BulkString = RespValue.BulkString(bytes)
}
object Key {
def apply[A](data: A)(implicit codec: BinaryCodec, schema: Schema[A]): Key = Key(codec.encode(schema)(data))
}
final case class Value(bytes: Chunk[Byte]) extends RespArgument {
lazy val value: BulkString = RespValue.BulkString(bytes)
}
object Value {
def apply[A](data: A)(implicit codec: BinaryCodec, schema: Schema[A]): Value = Value(codec.encode(schema)(data))
}
}
/*
* Copyright 2021 John A. De Goes and the ZIO contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package zio.redis
import zio.Chunk
final case class RespCommand(args: Chunk[RespArgument]) {
def ++(that: RespCommand): RespCommand = RespCommand(this.args ++ that.args)
def mapArguments(f: RespArgument => RespArgument): RespCommand = RespCommand(args.map(f(_)))
}
object RespCommand {
def empty: RespCommand = new RespCommand(Chunk.empty)
def apply(args: Chunk[RespArgument]): RespCommand = new RespCommand(args)
def apply(args: RespArgument*): RespCommand = new RespCommand(Chunk.fromIterable(args))
def apply(arg: RespArgument): RespCommand = new RespCommand(Chunk.single(arg))
}
......@@ -26,10 +26,10 @@ final class SingleNodeExecutor(
) extends RedisExecutor {
// TODO NodeExecutor doesn't throw connection errors, timeout errors, it is hanging forever
def execute(command: Chunk[RespValue.BulkString]): IO[RedisError, RespValue] =
def execute(command: RespCommand): IO[RedisError, RespValue] =
Promise
.make[RedisError, RespValue]
.flatMap(promise => reqQueue.offer(Request(command, promise)) *> promise.await)
.flatMap(promise => reqQueue.offer(Request(command.args.map(_.value), promise)) *> promise.await)
/**
* Opens a connection to the server and launches send and receive operations. All failures are retried by opening a
......
......@@ -58,7 +58,7 @@ trait Cluster extends RedisEnvironment {
*/
final def setSlotStable(slot: Slot): IO[RedisError, Unit] = {
val command =
RedisCommand(ClusterSetSlots, Tuple2(LongInput, ArbitraryInput[String]()), UnitOutput, codec, executor)
RedisCommand(ClusterSetSlots, Tuple2(LongInput, ArbitraryValueInput[String]()), UnitOutput, codec, executor)
command.run((slot.number, Stable.stringify))
}
......@@ -76,7 +76,7 @@ trait Cluster extends RedisEnvironment {
final def setSlotMigrating(slot: Slot, nodeId: String): IO[RedisError, Unit] = {
val command = RedisCommand(
ClusterSetSlots,
Tuple3(LongInput, ArbitraryInput[String](), ArbitraryInput[String]()),
Tuple3(LongInput, ArbitraryValueInput[String](), ArbitraryValueInput[String]()),
UnitOutput,
codec,
executor
......@@ -98,7 +98,7 @@ trait Cluster extends RedisEnvironment {
final def setSlotImporting(slot: Slot, nodeId: String): IO[RedisError, Unit] = {
val command = RedisCommand(
ClusterSetSlots,
Tuple3(LongInput, ArbitraryInput[String](), ArbitraryInput[String]()),
Tuple3(LongInput, ArbitraryValueInput[String](), ArbitraryValueInput[String]()),
UnitOutput,
codec,
executor
......@@ -120,7 +120,7 @@ trait Cluster extends RedisEnvironment {
final def setSlotNode(slot: Slot, nodeId: String): IO[RedisError, Unit] = {
val command = RedisCommand(
ClusterSetSlots,
Tuple3(LongInput, ArbitraryInput[String](), ArbitraryInput[String]()),
Tuple3(LongInput, ArbitraryValueInput[String](), ArbitraryValueInput[String]()),
UnitOutput,
codec,
executor
......
......@@ -44,7 +44,7 @@ trait Geo extends RedisEnvironment {
): IO[RedisError, Long] = {
val command = RedisCommand(
GeoAdd,
Tuple2(ArbitraryInput[K](), NonEmptyList(Tuple2(LongLatInput, ArbitraryInput[M]()))),
Tuple2(ArbitraryKeyInput[K](), NonEmptyList(Tuple2(LongLatInput, ArbitraryValueInput[M]()))),
LongOutput,
codec,
executor
......@@ -74,7 +74,12 @@ trait Geo extends RedisEnvironment {
): IO[RedisError, Option[Double]] = {
val command = RedisCommand(
GeoDist,
Tuple4(ArbitraryInput[K](), ArbitraryInput[M](), ArbitraryInput[M](), OptionalInput(RadiusUnitInput)),
Tuple4(
ArbitraryKeyInput[K](),
ArbitraryValueInput[M](),
ArbitraryValueInput[M](),
OptionalInput(RadiusUnitInput)
),
OptionalOutput(DoubleOutput),
codec,
executor
......@@ -102,7 +107,7 @@ trait Geo extends RedisEnvironment {
): IO[RedisError, Chunk[Option[String]]] = {
val command = RedisCommand(
GeoHash,
Tuple2(ArbitraryInput[K](), NonEmptyList(ArbitraryInput[M]())),
Tuple2(ArbitraryKeyInput[K](), NonEmptyList(ArbitraryValueInput[M]())),
ChunkOutput(OptionalOutput(MultiStringOutput)),
codec,
executor
......@@ -129,7 +134,13 @@ trait Geo extends RedisEnvironment {
members: M*
): IO[RedisError, Chunk[Option[LongLat]]] = {
val command =
RedisCommand(GeoPos, Tuple2(ArbitraryInput[K](), NonEmptyList(ArbitraryInput[M]())), GeoOutput, codec, executor)
RedisCommand(
GeoPos,
Tuple2(ArbitraryKeyInput[K](), NonEmptyList(ArbitraryValueInput[M]())),
GeoOutput,
codec,
executor
)
command.run((key, (member, members.toList)))
}
......@@ -172,7 +183,7 @@ trait Geo extends RedisEnvironment {
val command = RedisCommand(
GeoRadius,
Tuple9(
ArbitraryInput[K](),
ArbitraryKeyInput[K](),
LongLatInput,
DoubleInput,
RadiusUnitInput,
......@@ -235,7 +246,7 @@ trait Geo extends RedisEnvironment {
val command = RedisCommand(
GeoRadius,
Tuple11(
ArbitraryInput[K](),
ArbitraryKeyInput[K](),
LongLatInput,
DoubleInput,
RadiusUnitInput,
......@@ -295,8 +306,8 @@ trait Geo extends RedisEnvironment {
val command = RedisCommand(
GeoRadiusByMember,
Tuple9(
ArbitraryInput[K](),
ArbitraryInput[M](),
ArbitraryKeyInput[K](),
ArbitraryValueInput[M](),
DoubleInput,
RadiusUnitInput,
OptionalInput(WithCoordInput),
......@@ -358,8 +369,8 @@ trait Geo extends RedisEnvironment {
val command = RedisCommand(
GeoRadiusByMember,
Tuple11(
ArbitraryInput[K](),
ArbitraryInput[M](),
ArbitraryKeyInput[K](),
ArbitraryValueInput[M](),
DoubleInput,
RadiusUnitInput,
OptionalInput(WithCoordInput),
......
......@@ -40,7 +40,13 @@ trait Hashes extends RedisEnvironment {
*/
final def hDel[K: Schema, F: Schema](key: K, field: F, fields: F*): IO[RedisError, Long] = {
val command =
RedisCommand(HDel, Tuple2(ArbitraryInput[K](), NonEmptyList(ArbitraryInput[F]())), LongOutput, codec, executor)
RedisCommand(
HDel,
Tuple2(ArbitraryKeyInput[K](), NonEmptyList(ArbitraryValueInput[F]())),
LongOutput,
codec,
executor
)
command.run((key, (field, fields.toList)))
}
......@@ -55,7 +61,8 @@ trait Hashes extends RedisEnvironment {
* true if the field exists, otherwise false.
*/
final def hExists[K: Schema, F: Schema](key: K, field: F): IO[RedisError, Boolean] = {
val command = RedisCommand(HExists, Tuple2(ArbitraryInput[K](), ArbitraryInput[F]()), BoolOutput, codec, executor)
val command =
RedisCommand(HExists, Tuple2(ArbitraryKeyInput[K](), ArbitraryValueInput[F]()), BoolOutput, codec, executor)
command.run((key, field))
}
......@@ -74,7 +81,7 @@ trait Hashes extends RedisEnvironment {
def returning[V: Schema]: IO[RedisError, Option[V]] =
RedisCommand(
HGet,
Tuple2(ArbitraryInput[K](), ArbitraryInput[F]()),
Tuple2(ArbitraryKeyInput[K](), ArbitraryValueInput[F]()),
OptionalOutput(ArbitraryOutput[V]()),
codec,
executor
......@@ -95,7 +102,7 @@ trait Hashes extends RedisEnvironment {
val command =
RedisCommand(
HGetAll,
ArbitraryInput[K](),
ArbitraryKeyInput[K](),
KeyValueOutput(ArbitraryOutput[F](), ArbitraryOutput[V]()),
codec,
executor
......@@ -119,7 +126,13 @@ trait Hashes extends RedisEnvironment {
*/
final def hIncrBy[K: Schema, F: Schema](key: K, field: F, increment: Long): IO[RedisError, Long] = {
val command =
RedisCommand(HIncrBy, Tuple3(ArbitraryInput[K](), ArbitraryInput[F](), LongInput), LongOutput, codec, executor)
RedisCommand(
HIncrBy,
Tuple3(ArbitraryKeyInput[K](), ArbitraryValueInput[F](), LongInput),
LongOutput,
codec,
executor
)
command.run((key, field, increment))
}
......@@ -144,7 +157,7 @@ trait Hashes extends RedisEnvironment {
val command =
RedisCommand(
HIncrByFloat,
Tuple3(ArbitraryInput[K](), ArbitraryInput[F](), DoubleInput),
Tuple3(ArbitraryKeyInput[K](), ArbitraryValueInput[F](), DoubleInput),
DoubleOutput,
codec,
executor
......@@ -163,7 +176,7 @@ trait Hashes extends RedisEnvironment {
final def hKeys[K: Schema](key: K): ResultBuilder1[Chunk] =
new ResultBuilder1[Chunk] {
def returning[F: Schema]: IO[RedisError, Chunk[F]] =
RedisCommand(HKeys, ArbitraryInput[K](), ChunkOutput(ArbitraryOutput[F]()), codec, executor).run(key)
RedisCommand(HKeys, ArbitraryKeyInput[K](), ChunkOutput(ArbitraryOutput[F]()), codec, executor).run(key)
}
/**
......@@ -175,7 +188,7 @@ trait Hashes extends RedisEnvironment {
* number of fields.
*/
final def hLen[K: Schema](key: K): IO[RedisError, Long] = {
val command = RedisCommand(HLen, ArbitraryInput[K](), LongOutput, codec, executor)
val command = RedisCommand(HLen, ArbitraryKeyInput[K](), LongOutput, codec, executor)
command.run(key)
}
......@@ -200,7 +213,7 @@ trait Hashes extends RedisEnvironment {
def returning[V: Schema]: IO[RedisError, Chunk[Option[V]]] = {
val command = RedisCommand(
HmGet,
Tuple2(ArbitraryInput[K](), NonEmptyList(ArbitraryInput[F]())),
Tuple2(ArbitraryKeyInput[K](), NonEmptyList(ArbitraryValueInput[F]())),
ChunkOutput(OptionalOutput(ArbitraryOutput[V]())),
codec,
executor
......@@ -229,7 +242,7 @@ trait Hashes extends RedisEnvironment {
): IO[RedisError, Unit] = {
val command = RedisCommand(
HmSet,
Tuple2(ArbitraryInput[K](), NonEmptyList(Tuple2(ArbitraryInput[F](), ArbitraryInput[V]()))),
Tuple2(ArbitraryKeyInput[K](), NonEmptyList(Tuple2(ArbitraryValueInput[F](), ArbitraryValueInput[V]()))),
UnitOutput,
codec,
executor
......@@ -261,7 +274,7 @@ trait Hashes extends RedisEnvironment {
def returning[F: Schema, V: Schema]: IO[RedisError, (Long, Chunk[(F, V)])] = {
val command = RedisCommand(
HScan,
Tuple4(ArbitraryInput[K](), LongInput, OptionalInput(PatternInput), OptionalInput(CountInput)),
Tuple4(ArbitraryKeyInput[K](), LongInput, OptionalInput(PatternInput), OptionalInput(CountInput)),
Tuple2Output(ArbitraryOutput[Long](), ChunkTuple2Output(ArbitraryOutput[F](), ArbitraryOutput[V]())),
codec,
executor
......@@ -289,7 +302,7 @@ trait Hashes extends RedisEnvironment {
): IO[RedisError, Long] = {
val command = RedisCommand(
HSet,
Tuple2(ArbitraryInput[K](), NonEmptyList(Tuple2(ArbitraryInput[F](), ArbitraryInput[V]()))),
Tuple2(ArbitraryKeyInput[K](), NonEmptyList(Tuple2(ArbitraryValueInput[F](), ArbitraryValueInput[V]()))),
LongOutput,
codec,
executor
......@@ -317,7 +330,7 @@ trait Hashes extends RedisEnvironment {
val command =
RedisCommand(
HSetNx,
Tuple3(ArbitraryInput[K](), ArbitraryInput[F](), ArbitraryInput[V]()),
Tuple3(ArbitraryKeyInput[K](), ArbitraryValueInput[F](), ArbitraryValueInput[V]()),
BoolOutput,
codec,
executor
......@@ -336,7 +349,8 @@ trait Hashes extends RedisEnvironment {
* string length of the value in field, or zero if either field or key do not exist.
*/
final def hStrLen[K: Schema, F: Schema](key: K, field: F): IO[RedisError, Long] = {
val command = RedisCommand(HStrLen, Tuple2(ArbitraryInput[K](), ArbitraryInput[F]()), LongOutput, codec, executor)
val command =
RedisCommand(HStrLen, Tuple2(ArbitraryKeyInput[K](), ArbitraryValueInput[F]()), LongOutput, codec, executor)
command.run((key, field))
}
......@@ -351,7 +365,7 @@ trait Hashes extends RedisEnvironment {
final def hVals[K: Schema](key: K): ResultBuilder1[Chunk] =
new ResultBuilder1[Chunk] {
def returning[V: Schema]: IO[RedisError, Chunk[V]] =
RedisCommand(HVals, ArbitraryInput[K](), ChunkOutput(ArbitraryOutput[V]()), codec, executor).run(key)
RedisCommand(HVals, ArbitraryKeyInput[K](), ChunkOutput(ArbitraryOutput[V]()), codec, executor).run(key)
}
/**
......@@ -365,7 +379,7 @@ trait Hashes extends RedisEnvironment {
final def hRandField[K: Schema](key: K): ResultBuilder1[Option] =
new ResultBuilder1[Option] {
def returning[V: Schema]: IO[RedisError, Option[V]] =
RedisCommand(HRandField, ArbitraryInput[K](), OptionalOutput(ArbitraryOutput[V]()), codec, executor).run(key)
RedisCommand(HRandField, ArbitraryKeyInput[K](), OptionalOutput(ArbitraryOutput[V]()), codec, executor).run(key)
}
/**
......@@ -387,7 +401,7 @@ trait Hashes extends RedisEnvironment {
def returning[V: Schema]: IO[RedisError, Chunk[V]] = {
val command = RedisCommand(
HRandField,
Tuple3(ArbitraryInput[K](), LongInput, OptionalInput(StringInput)),
Tuple3(ArbitraryKeyInput[K](), LongInput, OptionalInput(StringInput)),
ChunkOutput(ArbitraryOutput[V]()),
codec,
executor
......
......@@ -39,7 +39,13 @@ trait HyperLogLog extends RedisEnvironment {
*/
final def pfAdd[K: Schema, V: Schema](key: K, element: V, elements: V*): IO[RedisError, Boolean] = {
val command =
RedisCommand(PfAdd, Tuple2(ArbitraryInput[K](), NonEmptyList(ArbitraryInput[V]())), BoolOutput, codec, executor)
RedisCommand(
PfAdd,
Tuple2(ArbitraryKeyInput[K](), NonEmptyList(ArbitraryValueInput[V]())),
BoolOutput,
codec,
executor
)
command.run((key, (element, elements.toList)))
}
......@@ -54,7 +60,7 @@ trait HyperLogLog extends RedisEnvironment {
* approximate number of unique elements observed via PFADD.
*/
final def pfCount[K: Schema](key: K, keys: K*): IO[RedisError, Long] = {
val command = RedisCommand(PfCount, NonEmptyList(ArbitraryInput[K]()), LongOutput, codec, executor)
val command = RedisCommand(PfCount, NonEmptyList(ArbitraryKeyInput[K]()), LongOutput, codec, executor)
command.run((key, keys.toList))
}
......@@ -70,7 +76,13 @@ trait HyperLogLog extends RedisEnvironment {
*/
final def pfMerge[K: Schema](destKey: K, sourceKey: K, sourceKeys: K*): IO[RedisError, Unit] = {
val command =
RedisCommand(PfMerge, Tuple2(ArbitraryInput[K](), NonEmptyList(ArbitraryInput[K]())), UnitOutput, codec, executor)
RedisCommand(
PfMerge,
Tuple2(ArbitraryKeyInput[K](), NonEmptyList(ArbitraryKeyInput[K]())),
UnitOutput,
codec,
executor
)
command.run((destKey, (sourceKey, sourceKeys.toList)))
}
}
......
......@@ -42,7 +42,7 @@ trait Keys extends RedisEnvironment {
* [[unlink]]
*/
final def del[K: Schema](key: K, keys: K*): IO[RedisError, Long] = {
val command = RedisCommand(Del, NonEmptyList(ArbitraryInput[K]()), LongOutput, codec, executor)
val command = RedisCommand(Del, NonEmptyList(ArbitraryKeyInput[K]()), LongOutput, codec, executor)
command.run((key, keys.toList))
}
......@@ -55,7 +55,7 @@ trait Keys extends RedisEnvironment {
* bytes for value stored at key.
*/
final def dump[K: Schema](key: K): IO[RedisError, Chunk[Byte]] = {
val command = RedisCommand(Dump, ArbitraryInput[K](), BulkStringOutput, codec, executor)
val command = RedisCommand(Dump, ArbitraryKeyInput[K](), BulkStringOutput, codec, executor)
command.run(key)
}
......@@ -71,7 +71,7 @@ trait Keys extends RedisEnvironment {
* The number of keys existing.
*/
final def exists[K: Schema](key: K, keys: K*): IO[RedisError, Long] = {
val command = RedisCommand(Exists, NonEmptyList(ArbitraryInput[K]()), LongOutput, codec, executor)
val command = RedisCommand(Exists, NonEmptyList(ArbitraryKeyInput[K]()), LongOutput, codec, executor)
command.run((key, keys.toList))
}
......@@ -89,7 +89,8 @@ trait Keys extends RedisEnvironment {
* [[expireAt]]
*/
final def expire[K: Schema](key: K, timeout: Duration): IO[RedisError, Boolean] = {
val command = RedisCommand(Expire, Tuple2(ArbitraryInput[K](), DurationSecondsInput), BoolOutput, codec, executor)
val command =
RedisCommand(Expire, Tuple2(ArbitraryKeyInput[K](), DurationSecondsInput), BoolOutput, codec, executor)
command.run((key, timeout))
}
......@@ -107,7 +108,7 @@ trait Keys extends RedisEnvironment {
* [[expire]]
*/
final def expireAt[K: Schema](key: K, timestamp: Instant): IO[RedisError, Boolean] = {
val command = RedisCommand(ExpireAt, Tuple2(ArbitraryInput[K](), TimeSecondsInput), BoolOutput, codec, executor)
val command = RedisCommand(ExpireAt, Tuple2(ArbitraryKeyInput[K](), TimeSecondsInput), BoolOutput, codec, executor)
command.run((key, timestamp))
}
......@@ -166,13 +167,13 @@ trait Keys extends RedisEnvironment {
Tuple9(
StringInput,
LongInput,
ArbitraryInput[K](),
ArbitraryKeyInput[K](),
LongInput,
LongInput,
OptionalInput(CopyInput),
OptionalInput(ReplaceInput),
OptionalInput(AuthInput),
OptionalInput(NonEmptyList(ArbitraryInput[K]()))
OptionalInput(NonEmptyList(ArbitraryKeyInput[K]()))
),
StringOutput,
codec,
......@@ -193,7 +194,7 @@ trait Keys extends RedisEnvironment {
* true if the key was moved.
*/
final def move[K: Schema](key: K, destinationDb: Long): IO[RedisError, Boolean] = {
val command = RedisCommand(Move, Tuple2(ArbitraryInput[K](), LongInput), BoolOutput, codec, executor)
val command = RedisCommand(Move, Tuple2(ArbitraryKeyInput[K](), LongInput), BoolOutput, codec, executor)
command.run((key, destinationDb))
}
......@@ -206,7 +207,7 @@ trait Keys extends RedisEnvironment {
* true if timeout was removed, false if key does not exist or does not have an associated timeout.
*/
final def persist[K: Schema](key: K): IO[RedisError, Boolean] = {
val command = RedisCommand(Persist, ArbitraryInput[K](), BoolOutput, codec, executor)
val command = RedisCommand(Persist, ArbitraryKeyInput[K](), BoolOutput, codec, executor)
command.run(key)
}
......@@ -225,7 +226,7 @@ trait Keys extends RedisEnvironment {
*/
final def pExpire[K: Schema](key: K, timeout: Duration): IO[RedisError, Boolean] = {
val command =
RedisCommand(PExpire, Tuple2(ArbitraryInput[K](), DurationMillisecondsInput), BoolOutput, codec, executor)
RedisCommand(PExpire, Tuple2(ArbitraryKeyInput[K](), DurationMillisecondsInput), BoolOutput, codec, executor)
command.run((key, timeout))
}
......@@ -244,7 +245,7 @@ trait Keys extends RedisEnvironment {
*/
final def pExpireAt[K: Schema](key: K, timestamp: Instant): IO[RedisError, Boolean] = {
val command =
RedisCommand(PExpireAt, Tuple2(ArbitraryInput[K](), TimeMillisecondsInput), BoolOutput, codec, executor)
RedisCommand(PExpireAt, Tuple2(ArbitraryKeyInput[K](), TimeMillisecondsInput), BoolOutput, codec, executor)
command.run((key, timestamp))
}
......@@ -257,7 +258,7 @@ trait Keys extends RedisEnvironment {
* remaining time to live of a key that has a timeout, error otherwise.
*/
final def pTtl[K: Schema](key: K): IO[RedisError, Duration] = {
val command = RedisCommand(PTtl, ArbitraryInput[K](), DurationMillisecondsOutput, codec, executor)
val command = RedisCommand(PTtl, ArbitraryKeyInput[K](), DurationMillisecondsOutput, codec, executor)
command.run(key)
}
......@@ -284,7 +285,8 @@ trait Keys extends RedisEnvironment {
* unit if successful, error otherwise.
*/
final def rename[K: Schema](key: K, newKey: K): IO[RedisError, Unit] = {
val command = RedisCommand(Rename, Tuple2(ArbitraryInput[K](), ArbitraryInput[K]()), UnitOutput, codec, executor)
val command =
RedisCommand(Rename, Tuple2(ArbitraryKeyInput[K](), ArbitraryKeyInput[K]()), UnitOutput, codec, executor)
command.run((key, newKey))
}
......@@ -299,7 +301,8 @@ trait Keys extends RedisEnvironment {
* true if key was renamed to newKey, false if newKey already exists.
*/
final def renameNx[K: Schema](key: K, newKey: K): IO[RedisError, Boolean] = {
val command = RedisCommand(RenameNx, Tuple2(ArbitraryInput[K](), ArbitraryInput[K]()), BoolOutput, codec, executor)
val command =
RedisCommand(RenameNx, Tuple2(ArbitraryKeyInput[K](), ArbitraryKeyInput[K]()), BoolOutput, codec, executor)
command.run((key, newKey))
}
......@@ -337,9 +340,9 @@ trait Keys extends RedisEnvironment {
val command = RedisCommand(
Restore,
Tuple7(
ArbitraryInput[K](),
ArbitraryKeyInput[K](),
LongInput,
ByteInput,
ValueInput,
OptionalInput(ReplaceInput),
OptionalInput(AbsTtlInput),
OptionalInput(IdleTimeInput),
......@@ -418,7 +421,7 @@ trait Keys extends RedisEnvironment {
val command = RedisCommand(
Sort,
Tuple6(
ArbitraryInput[K](),
ArbitraryKeyInput[K](),
OptionalInput(ByInput),
OptionalInput(LimitInput),
OptionalInput(NonEmptyList(GetInput)),
......@@ -469,7 +472,7 @@ trait Keys extends RedisEnvironment {
val command = RedisCommand(
SortStore,
Tuple7(
ArbitraryInput[K](),
ArbitraryKeyInput[K](),
OptionalInput(ByInput),
OptionalInput(LimitInput),
OptionalInput(NonEmptyList(GetInput)),
......@@ -495,7 +498,7 @@ trait Keys extends RedisEnvironment {
* The number of keys that were touched.
*/
final def touch[K: Schema](key: K, keys: K*): IO[RedisError, Long] = {
val command = RedisCommand(Touch, NonEmptyList(ArbitraryInput[K]()), LongOutput, codec, executor)
val command = RedisCommand(Touch, NonEmptyList(ArbitraryKeyInput[K]()), LongOutput, codec, executor)
command.run((key, keys.toList))
}
......@@ -508,7 +511,7 @@ trait Keys extends RedisEnvironment {
* remaining time to live of a key that has a timeout, error otherwise.
*/
final def ttl[K: Schema](key: K): IO[RedisError, Duration] = {
val command = RedisCommand(Ttl, ArbitraryInput[K](), DurationSecondsOutput, codec, executor)
val command = RedisCommand(Ttl, ArbitraryKeyInput[K](), DurationSecondsOutput, codec, executor)
command.run(key)
}
......@@ -521,7 +524,7 @@ trait Keys extends RedisEnvironment {
* type of the value stored at key.
*/
final def typeOf[K: Schema](key: K): IO[RedisError, RedisType] = {
val command = RedisCommand(TypeOf, ArbitraryInput[K](), TypeOutput, codec, executor)
val command = RedisCommand(TypeOf, ArbitraryKeyInput[K](), TypeOutput, codec, executor)
command.run(key)
}
......@@ -540,7 +543,7 @@ trait Keys extends RedisEnvironment {
* [[del]]
*/
final def unlink[K: Schema](key: K, keys: K*): IO[RedisError, Long] = {
val command = RedisCommand(Unlink, NonEmptyList(ArbitraryInput[K]()), LongOutput, codec, executor)
val command = RedisCommand(Unlink, NonEmptyList(ArbitraryKeyInput[K]()), LongOutput, codec, executor)
command.run((key, keys.toList))
}
......
......@@ -49,7 +49,7 @@ trait Lists extends RedisEnvironment {
def returning[V: Schema]: IO[RedisError, Option[V]] = {
val command = RedisCommand(
BrPopLPush,
Tuple3(ArbitraryInput[S](), ArbitraryInput[D](), DurationSecondsInput),
Tuple3(ArbitraryValueInput[S](), ArbitraryValueInput[D](), DurationSecondsInput),
OptionalOutput(ArbitraryOutput[V]()),
codec,
executor
......@@ -75,7 +75,7 @@ trait Lists extends RedisEnvironment {
def returning[V: Schema]: IO[RedisError, Option[V]] =
RedisCommand(
LIndex,
Tuple2(ArbitraryInput[K](), LongInput),
Tuple2(ArbitraryKeyInput[K](), LongInput),
OptionalOutput(ArbitraryOutput[V]()),
codec,
executor
......@@ -92,7 +92,7 @@ trait Lists extends RedisEnvironment {
* the length of the list at key.
*/
final def lLen[K: Schema](key: K): IO[RedisError, Long] = {
val command = RedisCommand(LLen, ArbitraryInput[K](), LongOutput, codec, executor)
val command = RedisCommand(LLen, ArbitraryKeyInput[K](), LongOutput, codec, executor)
command.run(key)
}
......@@ -107,7 +107,7 @@ trait Lists extends RedisEnvironment {
final def lPop[K: Schema](key: K): ResultBuilder1[Option] =
new ResultBuilder1[Option] {
def returning[V: Schema]: IO[RedisError, Option[V]] =
RedisCommand(LPop, ArbitraryInput[K](), OptionalOutput(ArbitraryOutput[V]()), codec, executor).run(key)
RedisCommand(LPop, ArbitraryKeyInput[K](), OptionalOutput(ArbitraryOutput[V]()), codec, executor).run(key)
}
/**
......@@ -125,7 +125,13 @@ trait Lists extends RedisEnvironment {
*/
final def lPush[K: Schema, V: Schema](key: K, element: V, elements: V*): IO[RedisError, Long] = {
val command =
RedisCommand(LPush, Tuple2(ArbitraryInput[K](), NonEmptyList(ArbitraryInput[V]())), LongOutput, codec, executor)
RedisCommand(
LPush,
Tuple2(ArbitraryKeyInput[K](), NonEmptyList(ArbitraryValueInput[V]())),
LongOutput,
codec,
executor
)
command.run((key, (element, elements.toList)))
}
......@@ -144,7 +150,13 @@ trait Lists extends RedisEnvironment {
*/
final def lPushX[K: Schema, V: Schema](key: K, element: V, elements: V*): IO[RedisError, Long] = {
val command =
RedisCommand(LPushX, Tuple2(ArbitraryInput[K](), NonEmptyList(ArbitraryInput[V]())), LongOutput, codec, executor)
RedisCommand(
LPushX,
Tuple2(ArbitraryKeyInput[K](), NonEmptyList(ArbitraryValueInput[V]())),
LongOutput,
codec,
executor
)
command.run((key, (element, elements.toList)))
}
......@@ -164,7 +176,7 @@ trait Lists extends RedisEnvironment {
def returning[V: Schema]: IO[RedisError, Chunk[V]] =
RedisCommand(
LRange,
Tuple2(ArbitraryInput[K](), RangeInput),
Tuple2(ArbitraryKeyInput[K](), RangeInput),
ChunkOutput(ArbitraryOutput[V]()),
codec,
executor
......@@ -190,7 +202,8 @@ trait Lists extends RedisEnvironment {
* the number of removed elements.
*/
final def lRem[K: Schema](key: K, count: Long, element: String): IO[RedisError, Long] = {
val command = RedisCommand(LRem, Tuple3(ArbitraryInput[K](), LongInput, StringInput), LongOutput, codec, executor)
val command =
RedisCommand(LRem, Tuple3(ArbitraryKeyInput[K](), LongInput, StringInput), LongOutput, codec, executor)
command.run((key, count, element))
}
......@@ -208,7 +221,13 @@ trait Lists extends RedisEnvironment {
*/
final def lSet[K: Schema, V: Schema](key: K, index: Long, element: V): IO[RedisError, Unit] = {
val command =
RedisCommand(LSet, Tuple3(ArbitraryInput[K](), LongInput, ArbitraryInput[V]()), UnitOutput, codec, executor)
RedisCommand(
LSet,
Tuple3(ArbitraryKeyInput[K](), LongInput, ArbitraryValueInput[V]()),
UnitOutput,
codec,
executor
)
command.run((key, index, element))
}
......@@ -224,7 +243,7 @@ trait Lists extends RedisEnvironment {
* the Unit value.
*/
final def lTrim[K: Schema](key: K, range: Range): IO[RedisError, Unit] = {
val command = RedisCommand(LTrim, Tuple2(ArbitraryInput[K](), RangeInput), UnitOutput, codec, executor)
val command = RedisCommand(LTrim, Tuple2(ArbitraryKeyInput[K](), RangeInput), UnitOutput, codec, executor)
command.run((key, range))
}
......@@ -239,7 +258,7 @@ trait Lists extends RedisEnvironment {
final def rPop[K: Schema](key: K): ResultBuilder1[Option] =
new ResultBuilder1[Option] {
def returning[V: Schema]: IO[RedisError, Option[V]] =
RedisCommand(RPop, ArbitraryInput[K](), OptionalOutput(ArbitraryOutput[V]()), codec, executor).run(key)
RedisCommand(RPop, ArbitraryKeyInput[K](), OptionalOutput(ArbitraryOutput[V]()), codec, executor).run(key)
}
/**
......@@ -259,7 +278,7 @@ trait Lists extends RedisEnvironment {
def returning[V: Schema]: IO[RedisError, Option[V]] =
RedisCommand(
RPopLPush,
Tuple2(ArbitraryInput[S](), ArbitraryInput[D]()),
Tuple2(ArbitraryValueInput[S](), ArbitraryValueInput[D]()),
OptionalOutput(ArbitraryOutput[V]()),
codec,
executor
......@@ -282,7 +301,13 @@ trait Lists extends RedisEnvironment {
*/
final def rPush[K: Schema, V: Schema](key: K, element: V, elements: V*): IO[RedisError, Long] = {
val command =
RedisCommand(RPush, Tuple2(ArbitraryInput[K](), NonEmptyList(ArbitraryInput[V]())), LongOutput, codec, executor)
RedisCommand(
RPush,
Tuple2(ArbitraryKeyInput[K](), NonEmptyList(ArbitraryValueInput[V]())),
LongOutput,
codec,
executor
)
command.run((key, (element, elements.toList)))
}
......@@ -301,7 +326,13 @@ trait Lists extends RedisEnvironment {
*/
final def rPushX[K: Schema, V: Schema](key: K, element: V, elements: V*): IO[RedisError, Long] = {
val command =
RedisCommand(RPushX, Tuple2(ArbitraryInput[K](), NonEmptyList(ArbitraryInput[V]())), LongOutput, codec, executor)
RedisCommand(
RPushX,
Tuple2(ArbitraryKeyInput[K](), NonEmptyList(ArbitraryValueInput[V]())),
LongOutput,
codec,
executor
)
command.run((key, (element, elements.toList)))
}
......@@ -327,7 +358,7 @@ trait Lists extends RedisEnvironment {
def returning[V: Schema]: IO[RedisError, Option[(K, V)]] = {
val command = RedisCommand(
BlPop,
Tuple2(NonEmptyList(ArbitraryInput[K]()), DurationSecondsInput),
Tuple2(NonEmptyList(ArbitraryKeyInput[K]()), DurationSecondsInput),
OptionalOutput(Tuple2Output(ArbitraryOutput[K](), ArbitraryOutput[V]())),
codec,
executor
......@@ -358,7 +389,7 @@ trait Lists extends RedisEnvironment {
def returning[V: Schema]: IO[RedisError, Option[(K, V)]] = {
val command = RedisCommand(
BrPop,
Tuple2(NonEmptyList(ArbitraryInput[K]()), DurationSecondsInput),
Tuple2(NonEmptyList(ArbitraryKeyInput[K]()), DurationSecondsInput),
OptionalOutput(Tuple2Output(ArbitraryOutput[K](), ArbitraryOutput[V]())),
codec,
executor
......@@ -389,7 +420,7 @@ trait Lists extends RedisEnvironment {
): IO[RedisError, Long] = {
val command = RedisCommand(
LInsert,
Tuple4(ArbitraryInput[K](), PositionInput, ArbitraryInput[V](), ArbitraryInput[V]()),
Tuple4(ArbitraryKeyInput[K](), PositionInput, ArbitraryValueInput[V](), ArbitraryValueInput[V]()),
LongOutput,
codec,
executor
......@@ -423,7 +454,7 @@ trait Lists extends RedisEnvironment {
def returning[V: Schema]: IO[RedisError, Option[V]] = {
val command = RedisCommand(
LMove,
Tuple4(ArbitraryInput[S](), ArbitraryInput[D](), SideInput, SideInput),
Tuple4(ArbitraryValueInput[S](), ArbitraryValueInput[D](), SideInput, SideInput),
OptionalOutput(ArbitraryOutput[V]()),
codec,
executor
......@@ -462,7 +493,7 @@ trait Lists extends RedisEnvironment {
def returning[V: Schema]: IO[RedisError, Option[V]] = {
val command = RedisCommand(
BlMove,
Tuple5(ArbitraryInput[S](), ArbitraryInput[D](), SideInput, SideInput, DurationSecondsInput),
Tuple5(ArbitraryValueInput[S](), ArbitraryValueInput[D](), SideInput, SideInput, DurationSecondsInput),
OptionalOutput(ArbitraryOutput[V]()),
codec,
executor
......@@ -497,8 +528,8 @@ trait Lists extends RedisEnvironment {
val command = RedisCommand(
LPos,
Tuple4(
ArbitraryInput[K](),
ArbitraryInput[V](),
ArbitraryKeyInput[K](),
ArbitraryValueInput[V](),
OptionalInput(RankInput),
OptionalInput(ListMaxLenInput)
),
......@@ -538,8 +569,8 @@ trait Lists extends RedisEnvironment {
val command = RedisCommand(
LPos,
Tuple5(
ArbitraryInput[K](),
ArbitraryInput[V](),
ArbitraryKeyInput[K](),
ArbitraryValueInput[V](),
CountInput,
OptionalInput(RankInput),
OptionalInput(ListMaxLenInput)
......
......@@ -41,7 +41,13 @@ trait Sets extends RedisEnvironment {
*/
final def sAdd[K: Schema, M: Schema](key: K, member: M, members: M*): IO[RedisError, Long] = {
val command =
RedisCommand(SAdd, Tuple2(ArbitraryInput[K](), NonEmptyList(ArbitraryInput[M]())), LongOutput, codec, executor)
RedisCommand(
SAdd,
Tuple2(ArbitraryKeyInput[K](), NonEmptyList(ArbitraryValueInput[M]())),
LongOutput,
codec,
executor
)
command.run((key, (member, members.toList)))
}
......@@ -54,7 +60,7 @@ trait Sets extends RedisEnvironment {
* Returns the cardinality (number of elements) of the set, or 0 if key does not exist.
*/
final def sCard[K: Schema](key: K): IO[RedisError, Long] = {
val command = RedisCommand(SCard, ArbitraryInput[K](), LongOutput, codec, executor)
val command = RedisCommand(SCard, ArbitraryKeyInput[K](), LongOutput, codec, executor)
command.run(key)
}
......@@ -71,7 +77,7 @@ trait Sets extends RedisEnvironment {
final def sDiff[K: Schema](key: K, keys: K*): ResultBuilder1[Chunk] =
new ResultBuilder1[Chunk] {
def returning[R: Schema]: IO[RedisError, Chunk[R]] =
RedisCommand(SDiff, NonEmptyList(ArbitraryInput[K]()), ChunkOutput(ArbitraryOutput[R]()), codec, executor)
RedisCommand(SDiff, NonEmptyList(ArbitraryKeyInput[K]()), ChunkOutput(ArbitraryOutput[R]()), codec, executor)
.run((key, keys.toList))
}
......@@ -90,7 +96,7 @@ trait Sets extends RedisEnvironment {
final def sDiffStore[D: Schema, K: Schema](destination: D, key: K, keys: K*): IO[RedisError, Long] = {
val command = RedisCommand(
SDiffStore,
Tuple2(ArbitraryInput[D](), NonEmptyList(ArbitraryInput[K]())),
Tuple2(ArbitraryValueInput[D](), NonEmptyList(ArbitraryKeyInput[K]())),
LongOutput,
codec,
executor
......@@ -111,7 +117,7 @@ trait Sets extends RedisEnvironment {
final def sInter[K: Schema](destination: K, keys: K*): ResultBuilder1[Chunk] =
new ResultBuilder1[Chunk] {
def returning[R: Schema]: IO[RedisError, Chunk[R]] =
RedisCommand(SInter, NonEmptyList(ArbitraryInput[K]()), ChunkOutput(ArbitraryOutput[R]()), codec, executor)
RedisCommand(SInter, NonEmptyList(ArbitraryKeyInput[K]()), ChunkOutput(ArbitraryOutput[R]()), codec, executor)
.run((destination, keys.toList))
}
......@@ -134,7 +140,7 @@ trait Sets extends RedisEnvironment {
): IO[RedisError, Long] = {
val command = RedisCommand(
SInterStore,
Tuple2(ArbitraryInput[D](), NonEmptyList(ArbitraryInput[K]())),
Tuple2(ArbitraryValueInput[D](), NonEmptyList(ArbitraryKeyInput[K]())),
LongOutput,
codec,
executor
......@@ -154,7 +160,8 @@ trait Sets extends RedisEnvironment {
* exist.
*/
final def sIsMember[K: Schema, M: Schema](key: K, member: M): IO[RedisError, Boolean] = {
val command = RedisCommand(SIsMember, Tuple2(ArbitraryInput[K](), ArbitraryInput[M]()), BoolOutput, codec, executor)
val command =
RedisCommand(SIsMember, Tuple2(ArbitraryKeyInput[K](), ArbitraryValueInput[M]()), BoolOutput, codec, executor)
command.run((key, member))
}
......@@ -169,7 +176,7 @@ trait Sets extends RedisEnvironment {
final def sMembers[K: Schema](key: K): ResultBuilder1[Chunk] =
new ResultBuilder1[Chunk] {
def returning[R: Schema]: IO[RedisError, Chunk[R]] =
RedisCommand(SMembers, ArbitraryInput[K](), ChunkOutput(ArbitraryOutput[R]()), codec, executor).run(key)
RedisCommand(SMembers, ArbitraryKeyInput[K](), ChunkOutput(ArbitraryOutput[R]()), codec, executor).run(key)
}
/**
......@@ -191,7 +198,7 @@ trait Sets extends RedisEnvironment {
): IO[RedisError, Boolean] = {
val command = RedisCommand(
SMove,
Tuple3(ArbitraryInput[S](), ArbitraryInput[D](), ArbitraryInput[M]()),
Tuple3(ArbitraryValueInput[S](), ArbitraryValueInput[D](), ArbitraryValueInput[M]()),
BoolOutput,
codec,
executor
......@@ -214,7 +221,7 @@ trait Sets extends RedisEnvironment {
def returning[R: Schema]: IO[RedisError, Chunk[R]] = {
val command = RedisCommand(
SPop,
Tuple2(ArbitraryInput[K](), OptionalInput(LongInput)),
Tuple2(ArbitraryKeyInput[K](), OptionalInput(LongInput)),
MultiStringChunkOutput(ArbitraryOutput[R]()),
codec,
executor
......@@ -238,7 +245,7 @@ trait Sets extends RedisEnvironment {
def returning[R: Schema]: IO[RedisError, Chunk[R]] = {
val command = RedisCommand(
SRandMember,
Tuple2(ArbitraryInput[K](), OptionalInput(LongInput)),
Tuple2(ArbitraryKeyInput[K](), OptionalInput(LongInput)),
MultiStringChunkOutput(ArbitraryOutput[R]()),
codec,
executor
......@@ -261,7 +268,13 @@ trait Sets extends RedisEnvironment {
*/
final def sRem[K: Schema, M: Schema](key: K, member: M, members: M*): IO[RedisError, Long] = {
val command =
RedisCommand(SRem, Tuple2(ArbitraryInput[K](), NonEmptyList(ArbitraryInput[M]())), LongOutput, codec, executor)
RedisCommand(
SRem,
Tuple2(ArbitraryKeyInput[K](), NonEmptyList(ArbitraryValueInput[M]())),
LongOutput,
codec,
executor
)
command.run((key, (member, members.toList)))
}
......@@ -292,7 +305,7 @@ trait Sets extends RedisEnvironment {
def returning[R: Schema]: IO[RedisError, (Long, Chunk[R])] = {
val command = RedisCommand(
SScan,
Tuple4(ArbitraryInput[K](), LongInput, OptionalInput(PatternInput), OptionalInput(CountInput)),
Tuple4(ArbitraryKeyInput[K](), LongInput, OptionalInput(PatternInput), OptionalInput(CountInput)),
Tuple2Output(MultiStringOutput.map(_.toLong), ChunkOutput(ArbitraryOutput[R]())),
codec,
executor
......@@ -314,7 +327,7 @@ trait Sets extends RedisEnvironment {
final def sUnion[K: Schema](key: K, keys: K*): ResultBuilder1[Chunk] =
new ResultBuilder1[Chunk] {
def returning[R: Schema]: IO[RedisError, Chunk[R]] =
RedisCommand(SUnion, NonEmptyList(ArbitraryInput[K]()), ChunkOutput(ArbitraryOutput[R]()), codec, executor)
RedisCommand(SUnion, NonEmptyList(ArbitraryKeyInput[K]()), ChunkOutput(ArbitraryOutput[R]()), codec, executor)
.run((key, keys.toList))
}
......@@ -337,7 +350,7 @@ trait Sets extends RedisEnvironment {
): IO[RedisError, Long] = {
val command = RedisCommand(
SUnionStore,
Tuple2(ArbitraryInput[D](), NonEmptyList(ArbitraryInput[K]())),
Tuple2(ArbitraryValueInput[D](), NonEmptyList(ArbitraryKeyInput[K]())),
LongOutput,
codec,
executor
......
......@@ -53,7 +53,7 @@ trait SortedSets extends RedisEnvironment {
}
val command = RedisCommand(
BzPopMax,
Tuple2(NonEmptyList(ArbitraryInput[K]()), DurationSecondsInput),
Tuple2(NonEmptyList(ArbitraryKeyInput[K]()), DurationSecondsInput),
OptionalOutput(memberScoreOutput),
codec,
executor
......@@ -89,7 +89,7 @@ trait SortedSets extends RedisEnvironment {
}
val command = RedisCommand(
BzPopMin,
Tuple2(NonEmptyList(ArbitraryInput[K]()), DurationSecondsInput),
Tuple2(NonEmptyList(ArbitraryKeyInput[K]()), DurationSecondsInput),
OptionalOutput(memberScoreOutput),
codec,
executor
......@@ -122,7 +122,7 @@ trait SortedSets extends RedisEnvironment {
val command = RedisCommand(
ZAdd,
Tuple4(
ArbitraryInput[K](),
ArbitraryKeyInput[K](),
OptionalInput(UpdateInput),
OptionalInput(ChangedInput),
NonEmptyList(MemberScoreInput[M]())
......@@ -161,7 +161,7 @@ trait SortedSets extends RedisEnvironment {
val command = RedisCommand(
ZAdd,
Tuple5(
ArbitraryInput[K](),
ArbitraryKeyInput[K](),
OptionalInput(UpdateInput),
OptionalInput(ChangedInput),
IncrementInput,
......@@ -183,7 +183,7 @@ trait SortedSets extends RedisEnvironment {
* The cardinality (number of elements) of the sorted set, or 0 if key does not exist.
*/
final def zCard[K: Schema](key: K): IO[RedisError, Long] = {
val command = RedisCommand(ZCard, ArbitraryInput[K](), LongOutput, codec, executor)
val command = RedisCommand(ZCard, ArbitraryKeyInput[K](), LongOutput, codec, executor)
command.run(key)
}
......@@ -198,7 +198,7 @@ trait SortedSets extends RedisEnvironment {
* the number of elements in the specified score range.
*/
final def zCount[K: Schema](key: K, range: Range): IO[RedisError, Long] = {
val command = RedisCommand(ZCount, Tuple2(ArbitraryInput[K](), RangeInput), LongOutput, codec, executor)
val command = RedisCommand(ZCount, Tuple2(ArbitraryKeyInput[K](), RangeInput), LongOutput, codec, executor)
command.run((key, range))
}
......@@ -226,7 +226,7 @@ trait SortedSets extends RedisEnvironment {
ZDiff,
Tuple2(
LongInput,
NonEmptyList(ArbitraryInput[K]())
NonEmptyList(ArbitraryKeyInput[K]())
),
ChunkOutput(ArbitraryOutput[M]()),
codec,
......@@ -260,8 +260,8 @@ trait SortedSets extends RedisEnvironment {
ZDiff,
Tuple3(
LongInput,
NonEmptyList(ArbitraryInput[K]()),
ArbitraryInput[String]()
NonEmptyList(ArbitraryKeyInput[K]()),
ArbitraryValueInput[String]()
),
ChunkTuple2Output(ArbitraryOutput[M](), DoubleOutput)
.map(_.map { case (m, s) => MemberScore(s, m) }),
......@@ -296,9 +296,9 @@ trait SortedSets extends RedisEnvironment {
RedisCommand(
ZDiffStore,
Tuple3(
ArbitraryInput[DK](),
ArbitraryValueInput[DK](),
LongInput,
NonEmptyList(ArbitraryInput[K]())
NonEmptyList(ArbitraryKeyInput[K]())
),
LongOutput,
codec,
......@@ -325,7 +325,13 @@ trait SortedSets extends RedisEnvironment {
member: M
): IO[RedisError, Double] = {
val command =
RedisCommand(ZIncrBy, Tuple3(ArbitraryInput[K](), LongInput, ArbitraryInput[M]()), DoubleOutput, codec, executor)
RedisCommand(
ZIncrBy,
Tuple3(ArbitraryKeyInput[K](), LongInput, ArbitraryValueInput[M]()),
DoubleOutput,
codec,
executor
)
command.run((key, increment, member))
}
......@@ -357,7 +363,7 @@ trait SortedSets extends RedisEnvironment {
ZInter,
Tuple4(
LongInput,
NonEmptyList(ArbitraryInput[K]()),
NonEmptyList(ArbitraryKeyInput[K]()),
OptionalInput(AggregateInput),
OptionalInput(WeightsInput)
),
......@@ -397,10 +403,10 @@ trait SortedSets extends RedisEnvironment {
ZInter,
Tuple5(
LongInput,
NonEmptyList(ArbitraryInput[K]()),
NonEmptyList(ArbitraryKeyInput[K]()),
OptionalInput(AggregateInput),
OptionalInput(WeightsInput),
ArbitraryInput[String]()
ArbitraryValueInput[String]()
),
ChunkTuple2Output(ArbitraryOutput[M](), DoubleOutput)
.map(_.map { case (m, s) => MemberScore(s, m) }),
......@@ -438,9 +444,9 @@ trait SortedSets extends RedisEnvironment {
val command = RedisCommand(
ZInterStore,
Tuple5(
ArbitraryInput[DK](),
ArbitraryValueInput[DK](),
LongInput,
NonEmptyList(ArbitraryInput[K]()),
NonEmptyList(ArbitraryKeyInput[K]()),
OptionalInput(AggregateInput),
OptionalInput(WeightsInput)
),
......@@ -464,7 +470,7 @@ trait SortedSets extends RedisEnvironment {
final def zLexCount[K: Schema](key: K, lexRange: LexRange): IO[RedisError, Long] = {
val command = RedisCommand(
ZLexCount,
Tuple3(ArbitraryInput[K](), ArbitraryInput[String](), ArbitraryInput[String]()),
Tuple3(ArbitraryKeyInput[K](), ArbitraryValueInput[String](), ArbitraryValueInput[String]()),
LongOutput,
codec,
executor
......@@ -492,7 +498,7 @@ trait SortedSets extends RedisEnvironment {
def returning[M: Schema]: IO[RedisError, Chunk[MemberScore[M]]] = {
val command = RedisCommand(
ZPopMax,
Tuple2(ArbitraryInput[K](), OptionalInput(LongInput)),
Tuple2(ArbitraryKeyInput[K](), OptionalInput(LongInput)),
ChunkTuple2Output(ArbitraryOutput[M](), DoubleOutput)
.map(_.map { case (m, s) => MemberScore(s, m) }),
codec,
......@@ -522,7 +528,7 @@ trait SortedSets extends RedisEnvironment {
def returning[M: Schema]: IO[RedisError, Chunk[MemberScore[M]]] = {
val command = RedisCommand(
ZPopMin,
Tuple2(ArbitraryInput[K](), OptionalInput(LongInput)),
Tuple2(ArbitraryKeyInput[K](), OptionalInput(LongInput)),
ChunkTuple2Output(ArbitraryOutput[M](), DoubleOutput)
.map(_.map { case (m, s) => MemberScore(s, m) }),
codec,
......@@ -547,7 +553,7 @@ trait SortedSets extends RedisEnvironment {
def returning[M: Schema]: IO[RedisError, Chunk[M]] = {
val command = RedisCommand(
ZRange,
Tuple2(ArbitraryInput[K](), RangeInput),
Tuple2(ArbitraryKeyInput[K](), RangeInput),
ChunkOutput(ArbitraryOutput[M]()),
codec,
executor
......@@ -574,7 +580,7 @@ trait SortedSets extends RedisEnvironment {
def returning[M: Schema]: IO[RedisError, Chunk[MemberScore[M]]] = {
val command = RedisCommand(
ZRange,
Tuple3(ArbitraryInput[K](), RangeInput, ArbitraryInput[String]()),
Tuple3(ArbitraryKeyInput[K](), RangeInput, ArbitraryValueInput[String]()),
ChunkTuple2Output(ArbitraryOutput[M](), DoubleOutput)
.map(_.map { case (m, s) => MemberScore(s, m) }),
codec,
......@@ -606,7 +612,12 @@ trait SortedSets extends RedisEnvironment {
def returning[M: Schema]: IO[RedisError, Chunk[M]] = {
val command = RedisCommand(
ZRangeByLex,
Tuple4(ArbitraryInput[K](), ArbitraryInput[String](), ArbitraryInput[String](), OptionalInput(LimitInput)),
Tuple4(
ArbitraryKeyInput[K](),
ArbitraryValueInput[String](),
ArbitraryValueInput[String](),
OptionalInput(LimitInput)
),
ChunkOutput(ArbitraryOutput[M]()),
codec,
executor
......@@ -637,7 +648,12 @@ trait SortedSets extends RedisEnvironment {
def returning[M: Schema]: IO[RedisError, Chunk[M]] = {
val command = RedisCommand(
ZRangeByScore,
Tuple4(ArbitraryInput[K](), ArbitraryInput[String](), ArbitraryInput[String](), OptionalInput(LimitInput)),
Tuple4(
ArbitraryKeyInput[K](),
ArbitraryValueInput[String](),
ArbitraryValueInput[String](),
OptionalInput(LimitInput)
),
ChunkOutput(ArbitraryOutput[M]()),
codec,
executor
......@@ -669,10 +685,10 @@ trait SortedSets extends RedisEnvironment {
val command = RedisCommand(
ZRangeByScore,
Tuple5(
ArbitraryInput[K](),
ArbitraryInput[String](),
ArbitraryInput[String](),
ArbitraryInput[String](),
ArbitraryKeyInput[K](),
ArbitraryValueInput[String](),
ArbitraryValueInput[String](),
ArbitraryValueInput[String](),
OptionalInput(LimitInput)
),
ChunkTuple2Output(ArbitraryOutput[M](), DoubleOutput)
......@@ -696,7 +712,13 @@ trait SortedSets extends RedisEnvironment {
*/
final def zRank[K: Schema, M: Schema](key: K, member: M): IO[RedisError, Option[Long]] = {
val command =
RedisCommand(ZRank, Tuple2(ArbitraryInput[K](), ArbitraryInput[M]()), OptionalOutput(LongOutput), codec, executor)
RedisCommand(
ZRank,
Tuple2(ArbitraryKeyInput[K](), ArbitraryValueInput[M]()),
OptionalOutput(LongOutput),
codec,
executor
)
command.run((key, member))
}
......@@ -718,7 +740,13 @@ trait SortedSets extends RedisEnvironment {
restMembers: M*
): IO[RedisError, Long] = {
val command =
RedisCommand(ZRem, Tuple2(ArbitraryInput[K](), NonEmptyList(ArbitraryInput[M]())), LongOutput, codec, executor)
RedisCommand(
ZRem,
Tuple2(ArbitraryKeyInput[K](), NonEmptyList(ArbitraryValueInput[M]())),
LongOutput,
codec,
executor
)
command.run((key, (firstMember, restMembers.toList)))
}
......@@ -735,7 +763,7 @@ trait SortedSets extends RedisEnvironment {
final def zRemRangeByLex[K: Schema](key: K, lexRange: LexRange): IO[RedisError, Long] = {
val command = RedisCommand(
ZRemRangeByLex,
Tuple3(ArbitraryInput[K](), ArbitraryInput[String](), ArbitraryInput[String]()),
Tuple3(ArbitraryKeyInput[K](), ArbitraryValueInput[String](), ArbitraryValueInput[String]()),
LongOutput,
codec,
executor
......@@ -754,7 +782,7 @@ trait SortedSets extends RedisEnvironment {
* The number of elements removed.
*/
final def zRemRangeByRank[K: Schema](key: K, range: Range): IO[RedisError, Long] = {
val command = RedisCommand(ZRemRangeByRank, Tuple2(ArbitraryInput[K](), RangeInput), LongOutput, codec, executor)
val command = RedisCommand(ZRemRangeByRank, Tuple2(ArbitraryKeyInput[K](), RangeInput), LongOutput, codec, executor)
command.run((key, range))
}
......@@ -771,7 +799,7 @@ trait SortedSets extends RedisEnvironment {
final def zRemRangeByScore[K: Schema](key: K, scoreRange: ScoreRange): IO[RedisError, Long] = {
val command = RedisCommand(
ZRemRangeByScore,
Tuple3(ArbitraryInput[K](), ArbitraryInput[String](), ArbitraryInput[String]()),
Tuple3(ArbitraryKeyInput[K](), ArbitraryValueInput[String](), ArbitraryValueInput[String]()),
LongOutput,
codec,
executor
......@@ -794,7 +822,7 @@ trait SortedSets extends RedisEnvironment {
def returning[M: Schema]: IO[RedisError, Chunk[M]] = {
val command = RedisCommand(
ZRevRange,
Tuple2(ArbitraryInput[K](), RangeInput),
Tuple2(ArbitraryKeyInput[K](), RangeInput),
ChunkOutput(ArbitraryOutput[M]()),
codec,
executor
......@@ -821,7 +849,7 @@ trait SortedSets extends RedisEnvironment {
def returning[M: Schema]: IO[RedisError, Chunk[MemberScore[M]]] = {
val command = RedisCommand(
ZRevRange,
Tuple3(ArbitraryInput[K](), RangeInput, ArbitraryInput[String]()),
Tuple3(ArbitraryKeyInput[K](), RangeInput, ArbitraryValueInput[String]()),
ChunkTuple2Output(ArbitraryOutput[M](), DoubleOutput)
.map(_.map { case (m, s) => MemberScore(s, m) }),
codec,
......@@ -853,7 +881,12 @@ trait SortedSets extends RedisEnvironment {
def returning[M: Schema]: IO[RedisError, Chunk[M]] = {
val command = RedisCommand(
ZRevRangeByLex,
Tuple4(ArbitraryInput[K](), ArbitraryInput[String](), ArbitraryInput[String](), OptionalInput(LimitInput)),
Tuple4(
ArbitraryKeyInput[K](),
ArbitraryValueInput[String](),
ArbitraryValueInput[String](),
OptionalInput(LimitInput)
),
ChunkOutput(ArbitraryOutput[M]()),
codec,
executor
......@@ -885,9 +918,9 @@ trait SortedSets extends RedisEnvironment {
val command = RedisCommand(
ZRevRangeByScore,
Tuple4(
ArbitraryInput[K](),
ArbitraryInput[String](),
ArbitraryInput[String](),
ArbitraryKeyInput[K](),
ArbitraryValueInput[String](),
ArbitraryValueInput[String](),
OptionalInput(LimitInput)
),
ChunkOutput(ArbitraryOutput[M]()),
......@@ -921,10 +954,10 @@ trait SortedSets extends RedisEnvironment {
val command = RedisCommand(
ZRevRangeByScore,
Tuple5(
ArbitraryInput[K](),
ArbitraryInput[String](),
ArbitraryInput[String](),
ArbitraryInput[String](),
ArbitraryKeyInput[K](),
ArbitraryValueInput[String](),
ArbitraryValueInput[String](),
ArbitraryValueInput[String](),
OptionalInput(LimitInput)
),
ChunkTuple2Output(ArbitraryOutput[M](), DoubleOutput)
......@@ -949,7 +982,7 @@ trait SortedSets extends RedisEnvironment {
final def zRevRank[K: Schema, M: Schema](key: K, member: M): IO[RedisError, Option[Long]] = {
val command = RedisCommand(
ZRevRank,
Tuple2(ArbitraryInput[K](), ArbitraryInput[M]()),
Tuple2(ArbitraryKeyInput[K](), ArbitraryValueInput[M]()),
OptionalOutput(LongOutput),
codec,
executor
......@@ -983,7 +1016,7 @@ trait SortedSets extends RedisEnvironment {
ChunkTuple2Output(ArbitraryOutput[M](), DoubleOutput).map(_.map { case (m, s) => MemberScore(s, m) })
val command = RedisCommand(
ZScan,
Tuple4(ArbitraryInput[K](), LongInput, OptionalInput(PatternInput), OptionalInput(CountInput)),
Tuple4(ArbitraryKeyInput[K](), LongInput, OptionalInput(PatternInput), OptionalInput(CountInput)),
Tuple2Output(MultiStringOutput.map(_.toLong), memberScoresOutput),
codec,
executor
......@@ -1005,7 +1038,7 @@ trait SortedSets extends RedisEnvironment {
final def zScore[K: Schema, M: Schema](key: K, member: M): IO[RedisError, Option[Double]] = {
val command = RedisCommand(
ZScore,
Tuple2(ArbitraryInput[K](), ArbitraryInput[M]()),
Tuple2(ArbitraryKeyInput[K](), ArbitraryValueInput[M]()),
OptionalOutput(DoubleOutput),
codec,
executor
......@@ -1042,7 +1075,7 @@ trait SortedSets extends RedisEnvironment {
ZUnion,
Tuple4(
LongInput,
NonEmptyList(ArbitraryInput[K]()),
NonEmptyList(ArbitraryKeyInput[K]()),
OptionalInput(WeightsInput),
OptionalInput(AggregateInput)
),
......@@ -1083,10 +1116,10 @@ trait SortedSets extends RedisEnvironment {
ZUnion,
Tuple5(
LongInput,
NonEmptyList(ArbitraryInput[K]()),
NonEmptyList(ArbitraryKeyInput[K]()),
OptionalInput(WeightsInput),
OptionalInput(AggregateInput),
ArbitraryInput[String]()
ArbitraryValueInput[String]()
),
ChunkTuple2Output(ArbitraryOutput[M](), DoubleOutput)
.map(_.map { case (m, s) => MemberScore(s, m) }),
......@@ -1124,9 +1157,9 @@ trait SortedSets extends RedisEnvironment {
val command = RedisCommand(
ZUnionStore,
Tuple5(
ArbitraryInput[DK](),
ArbitraryValueInput[DK](),
LongInput,
NonEmptyList(ArbitraryInput[K]()),
NonEmptyList(ArbitraryKeyInput[K]()),
OptionalInput(WeightsInput),
OptionalInput(AggregateInput)
),
......@@ -1150,7 +1183,7 @@ trait SortedSets extends RedisEnvironment {
final def zMScore[K: Schema](key: K, keys: K*): IO[RedisError, Chunk[Option[Double]]] = {
val command = RedisCommand(
ZMScore,
NonEmptyList(ArbitraryInput[K]()),
NonEmptyList(ArbitraryKeyInput[K]()),
ChunkOutput(OptionalOutput(DoubleOutput)),
codec,
executor
......@@ -1169,7 +1202,8 @@ trait SortedSets extends RedisEnvironment {
final def zRandMember[K: Schema](key: K): ResultBuilder1[Option] =
new ResultBuilder1[Option] {
def returning[R: Schema]: IO[RedisError, Option[R]] =
RedisCommand(ZRandMember, ArbitraryInput[K](), OptionalOutput(ArbitraryOutput[R]()), codec, executor).run(key)
RedisCommand(ZRandMember, ArbitraryKeyInput[K](), OptionalOutput(ArbitraryOutput[R]()), codec, executor)
.run(key)
}
/**
......@@ -1191,7 +1225,7 @@ trait SortedSets extends RedisEnvironment {
def returning[M: Schema]: IO[RedisError, Chunk[M]] = {
val command = RedisCommand(
ZRandMember,
Tuple2(ArbitraryInput[K](), LongInput),
Tuple2(ArbitraryKeyInput[K](), LongInput),
ZRandMemberOutput(ArbitraryOutput[M]()),
codec,
executor
......@@ -1221,7 +1255,7 @@ trait SortedSets extends RedisEnvironment {
def returning[M: Schema]: IO[RedisError, Chunk[MemberScore[M]]] = {
val command = RedisCommand(
ZRandMember,
Tuple3(ArbitraryInput[K](), LongInput, ArbitraryInput[String]()),
Tuple3(ArbitraryKeyInput[K](), LongInput, ArbitraryValueInput[String]()),
ZRandMemberTuple2Output(ArbitraryOutput[M](), DoubleOutput)
.map(_.map { case (m, s) => MemberScore(s, m) }),
codec,
......
......@@ -50,7 +50,7 @@ trait Streams extends RedisEnvironment {
): IO[RedisError, Long] = {
val command = RedisCommand(
XAck,
Tuple3(ArbitraryInput[SK](), ArbitraryInput[G](), NonEmptyList(ArbitraryInput[I]())),
Tuple3(ArbitraryKeyInput[SK](), ArbitraryValueInput[G](), NonEmptyList(ArbitraryValueInput[I]())),
LongOutput,
codec,
executor
......@@ -83,10 +83,10 @@ trait Streams extends RedisEnvironment {
val command = RedisCommand(
XAdd,
Tuple4(
ArbitraryInput[SK](),
ArbitraryKeyInput[SK](),
OptionalInput(StreamMaxLenInput),
ArbitraryInput[I](),
NonEmptyList(Tuple2(ArbitraryInput[K](), ArbitraryInput[V]()))
ArbitraryValueInput[I](),
NonEmptyList(Tuple2(ArbitraryKeyInput[K](), ArbitraryValueInput[V]()))
),
ArbitraryOutput[R](),
codec,
......@@ -108,7 +108,7 @@ trait Streams extends RedisEnvironment {
key: SK
): ResultBuilder3[StreamInfo] = new ResultBuilder3[StreamInfo] {
def returning[RI: Schema, RK: Schema, RV: Schema]: IO[RedisError, StreamInfo[RI, RK, RV]] = {
val command = RedisCommand(XInfoStream, ArbitraryInput[SK](), StreamInfoOutput[RI, RK, RV](), codec, executor)
val command = RedisCommand(XInfoStream, ArbitraryKeyInput[SK](), StreamInfoOutput[RI, RK, RV](), codec, executor)
command.run(key)
}
}
......@@ -127,7 +127,7 @@ trait Streams extends RedisEnvironment {
def returning[RI: Schema, RK: Schema, RV: Schema]: IO[RedisError, FullStreamInfo[RI, RK, RV]] = {
val command = RedisCommand(
XInfoStream,
Tuple2(ArbitraryInput[SK](), ArbitraryInput[String]()),
Tuple2(ArbitraryKeyInput[SK](), ArbitraryValueInput[String]()),
StreamInfoFullOutput[RI, RK, RV](),
codec,
executor
......@@ -153,7 +153,7 @@ trait Streams extends RedisEnvironment {
def returning[RI: Schema, RK: Schema, RV: Schema]: IO[RedisError, FullStreamInfo[RI, RK, RV]] = {
val command = RedisCommand(
XInfoStream,
Tuple3(ArbitraryInput[SK](), ArbitraryInput[String](), CountInput),
Tuple3(ArbitraryKeyInput[SK](), ArbitraryValueInput[String](), CountInput),
StreamInfoFullOutput[RI, RK, RV](),
codec,
executor
......@@ -171,7 +171,7 @@ trait Streams extends RedisEnvironment {
* List of consumer groups associated with the stream stored at the specified key.
*/
final def xInfoGroups[SK: Schema](key: SK): IO[RedisError, Chunk[StreamGroupsInfo]] = {
val command = RedisCommand(XInfoGroups, ArbitraryInput[SK](), StreamGroupsInfoOutput, codec, executor)
val command = RedisCommand(XInfoGroups, ArbitraryKeyInput[SK](), StreamGroupsInfoOutput, codec, executor)
command.run(key)
}
......@@ -192,7 +192,7 @@ trait Streams extends RedisEnvironment {
val command =
RedisCommand(
XInfoConsumers,
Tuple2(ArbitraryInput[SK](), ArbitraryInput[SG]()),
Tuple2(ArbitraryKeyInput[SK](), ArbitraryValueInput[SG]()),
StreamConsumersInfoOutput,
codec,
executor
......@@ -232,10 +232,10 @@ trait Streams extends RedisEnvironment {
val command = RedisCommand(
XAdd,
Tuple4(
ArbitraryInput[SK](),
ArbitraryKeyInput[SK](),
OptionalInput(StreamMaxLenInput),
ArbitraryInput[I](),
NonEmptyList(Tuple2(ArbitraryInput[K](), ArbitraryInput[V]()))
ArbitraryValueInput[I](),
NonEmptyList(Tuple2(ArbitraryKeyInput[K](), ArbitraryValueInput[V]()))
),
ArbitraryOutput[R](),
codec,
......@@ -287,11 +287,11 @@ trait Streams extends RedisEnvironment {
val command = RedisCommand(
XClaim,
Tuple9(
ArbitraryInput[SK](),
ArbitraryInput[SG](),
ArbitraryInput[SC](),
ArbitraryKeyInput[SK](),
ArbitraryValueInput[SG](),
ArbitraryValueInput[SC](),
DurationMillisecondsInput,
NonEmptyList(ArbitraryInput[I]()),
NonEmptyList(ArbitraryValueInput[I]()),
OptionalInput(IdleInput),
OptionalInput(TimeInput),
OptionalInput(RetryCountInput),
......@@ -348,11 +348,11 @@ trait Streams extends RedisEnvironment {
val command = RedisCommand(
XClaim,
Tuple10(
ArbitraryInput[SK](),
ArbitraryInput[SG](),
ArbitraryInput[SC](),
ArbitraryKeyInput[SK](),
ArbitraryValueInput[SG](),
ArbitraryValueInput[SC](),
DurationMillisecondsInput,
NonEmptyList(ArbitraryInput[I]()),
NonEmptyList(ArbitraryValueInput[I]()),
OptionalInput(IdleInput),
OptionalInput(TimeInput),
OptionalInput(RetryCountInput),
......@@ -382,7 +382,13 @@ trait Streams extends RedisEnvironment {
*/
final def xDel[SK: Schema, I: Schema](key: SK, id: I, ids: I*): IO[RedisError, Long] = {
val command =
RedisCommand(XDel, Tuple2(ArbitraryInput[SK](), NonEmptyList(ArbitraryInput[I]())), LongOutput, codec, executor)
RedisCommand(
XDel,
Tuple2(ArbitraryKeyInput[SK](), NonEmptyList(ArbitraryValueInput[I]())),
LongOutput,
codec,
executor
)
command.run((key, (id, ids.toList)))
}
......@@ -491,7 +497,7 @@ trait Streams extends RedisEnvironment {
* the number of entries inside a stream.
*/
final def xLen[SK: Schema](key: SK): IO[RedisError, Long] = {
val command = RedisCommand(XLen, ArbitraryInput[SK](), LongOutput, codec, executor)
val command = RedisCommand(XLen, ArbitraryKeyInput[SK](), LongOutput, codec, executor)
command.run(key)
}
......@@ -508,7 +514,7 @@ trait Streams extends RedisEnvironment {
final def xPending[SK: Schema, SG: Schema](key: SK, group: SG): IO[RedisError, PendingInfo] = {
val command = RedisCommand(
XPending,
Tuple3(ArbitraryInput[SK](), ArbitraryInput[SG](), OptionalInput(IdleInput)),
Tuple3(ArbitraryKeyInput[SK](), ArbitraryValueInput[SG](), OptionalInput(IdleInput)),
XPendingOutput,
codec,
executor
......@@ -548,13 +554,13 @@ trait Streams extends RedisEnvironment {
val command = RedisCommand(
XPending,
Tuple7(
ArbitraryInput[SK](),
ArbitraryInput[SG](),
ArbitraryKeyInput[SK](),
ArbitraryValueInput[SG](),
OptionalInput(IdleInput),
ArbitraryInput[I](),
ArbitraryInput[I](),
ArbitraryValueInput[I](),
ArbitraryValueInput[I](),
LongInput,
OptionalInput(ArbitraryInput[SC]())
OptionalInput(ArbitraryValueInput[SC]())
),
PendingMessagesOutput,
codec,
......@@ -584,7 +590,12 @@ trait Streams extends RedisEnvironment {
def returning[RK: Schema, RV: Schema]: IO[RedisError, StreamEntries[I, RK, RV]] = {
val command = RedisCommand(
XRange,
Tuple4(ArbitraryInput[SK](), ArbitraryInput[I](), ArbitraryInput[I](), OptionalInput(CountInput)),
Tuple4(
ArbitraryKeyInput[SK](),
ArbitraryValueInput[I](),
ArbitraryValueInput[I](),
OptionalInput(CountInput)
),
StreamEntriesOutput[I, RK, RV](),
codec,
executor
......@@ -617,7 +628,12 @@ trait Streams extends RedisEnvironment {
def returning[RK: Schema, RV: Schema]: IO[RedisError, StreamEntries[I, RK, RV]] = {
val command = RedisCommand(
XRange,
Tuple4(ArbitraryInput[SK](), ArbitraryInput[I](), ArbitraryInput[I](), OptionalInput(CountInput)),
Tuple4(
ArbitraryKeyInput[SK](),
ArbitraryValueInput[I](),
ArbitraryValueInput[I](),
OptionalInput(CountInput)
),
StreamEntriesOutput[I, RK, RV](),
codec,
executor
......@@ -695,8 +711,8 @@ trait Streams extends RedisEnvironment {
val command = RedisCommand(
XReadGroup,
Tuple6(
ArbitraryInput[SG](),
ArbitraryInput[SC](),
ArbitraryValueInput[SG](),
ArbitraryValueInput[SC](),
OptionalInput(CountInput),
OptionalInput(BlockInput),
OptionalInput(NoAckInput),
......@@ -732,7 +748,12 @@ trait Streams extends RedisEnvironment {
def returning[RK: Schema, RV: Schema]: IO[RedisError, StreamEntries[I, RK, RV]] = {
val command = RedisCommand(
XRevRange,
Tuple4(ArbitraryInput[SK](), ArbitraryInput[I](), ArbitraryInput[I](), OptionalInput(CountInput)),
Tuple4(
ArbitraryKeyInput[SK](),
ArbitraryValueInput[I](),
ArbitraryValueInput[I](),
OptionalInput(CountInput)
),
StreamEntriesOutput[I, RK, RV](),
codec,
executor
......@@ -765,7 +786,12 @@ trait Streams extends RedisEnvironment {
def returning[RK: Schema, RV: Schema]: IO[RedisError, StreamEntries[I, RK, RV]] = {
val command = RedisCommand(
XRevRange,
Tuple4(ArbitraryInput[SK](), ArbitraryInput[I](), ArbitraryInput[I](), OptionalInput(CountInput)),
Tuple4(
ArbitraryKeyInput[SK](),
ArbitraryValueInput[I](),
ArbitraryValueInput[I](),
OptionalInput(CountInput)
),
StreamEntriesOutput[I, RK, RV](),
codec,
executor
......@@ -791,7 +817,7 @@ trait Streams extends RedisEnvironment {
count: Long,
approximate: Boolean = false
): IO[RedisError, Long] = {
val command = RedisCommand(XTrim, Tuple2(ArbitraryInput[SK](), StreamMaxLenInput), LongOutput, codec, executor)
val command = RedisCommand(XTrim, Tuple2(ArbitraryKeyInput[SK](), StreamMaxLenInput), LongOutput, codec, executor)
command.run((key, StreamMaxLen(approximate, count)))
}
}
......
......@@ -39,7 +39,8 @@ trait Strings extends RedisEnvironment {
* Returns the length of the string after the append operation.
*/
final def append[K: Schema, V: Schema](key: K, value: V): IO[RedisError, Long] = {
val command = RedisCommand(Append, Tuple2(ArbitraryInput[K](), ArbitraryInput[V]()), LongOutput, codec, executor)
val command =
RedisCommand(Append, Tuple2(ArbitraryKeyInput[K](), ArbitraryValueInput[V]()), LongOutput, codec, executor)
command.run((key, value))
}
......@@ -55,7 +56,7 @@ trait Strings extends RedisEnvironment {
*/
final def bitCount[K: Schema](key: K, range: Option[Range] = None): IO[RedisError, Long] = {
val command =
RedisCommand(BitCount, Tuple2(ArbitraryInput[K](), OptionalInput(RangeInput)), LongOutput, codec, executor)
RedisCommand(BitCount, Tuple2(ArbitraryKeyInput[K](), OptionalInput(RangeInput)), LongOutput, codec, executor)
command.run((key, range))
}
......@@ -78,7 +79,7 @@ trait Strings extends RedisEnvironment {
): IO[RedisError, Chunk[Option[Long]]] = {
val command = RedisCommand(
BitField,
Tuple2(ArbitraryInput[K](), NonEmptyList(BitFieldCommandInput)),
Tuple2(ArbitraryKeyInput[K](), NonEmptyList(BitFieldCommandInput)),
ChunkOutput(OptionalOutput(LongOutput)),
codec,
executor
......@@ -109,7 +110,7 @@ trait Strings extends RedisEnvironment {
val command =
RedisCommand(
BitOp,
Tuple3(BitOperationInput, ArbitraryInput[D](), NonEmptyList(ArbitraryInput[S]())),
Tuple3(BitOperationInput, ArbitraryValueInput[D](), NonEmptyList(ArbitraryValueInput[S]())),
LongOutput,
codec,
executor
......@@ -137,7 +138,7 @@ trait Strings extends RedisEnvironment {
val command =
RedisCommand(
BitPos,
Tuple3(ArbitraryInput[K](), BoolInput, OptionalInput(BitPosRangeInput)),
Tuple3(ArbitraryKeyInput[K](), BoolInput, OptionalInput(BitPosRangeInput)),
LongOutput,
codec,
executor
......@@ -154,7 +155,7 @@ trait Strings extends RedisEnvironment {
* Returns the value of key after the decrement.
*/
final def decr[K: Schema](key: K): IO[RedisError, Long] = {
val command = RedisCommand(Decr, ArbitraryInput[K](), LongOutput, codec, executor)
val command = RedisCommand(Decr, ArbitraryKeyInput[K](), LongOutput, codec, executor)
command.run(key)
}
......@@ -169,7 +170,7 @@ trait Strings extends RedisEnvironment {
* Returns the value of key after the decrement.
*/
final def decrBy[K: Schema](key: K, decrement: Long): IO[RedisError, Long] = {
val command = RedisCommand(DecrBy, Tuple2(ArbitraryInput[K](), LongInput), LongOutput, codec, executor)
val command = RedisCommand(DecrBy, Tuple2(ArbitraryKeyInput[K](), LongInput), LongOutput, codec, executor)
command.run((key, decrement))
}
......@@ -184,7 +185,7 @@ trait Strings extends RedisEnvironment {
final def get[K: Schema](key: K): ResultBuilder1[Option] =
new ResultBuilder1[Option] {
def returning[R: Schema]: IO[RedisError, Option[R]] =
RedisCommand(Get, ArbitraryInput[K](), OptionalOutput(ArbitraryOutput[R]()), codec, executor).run(key)
RedisCommand(Get, ArbitraryKeyInput[K](), OptionalOutput(ArbitraryOutput[R]()), codec, executor).run(key)
}
/**
......@@ -198,7 +199,7 @@ trait Strings extends RedisEnvironment {
* Returns the bit value stored at offset.
*/
final def getBit[K: Schema](key: K, offset: Long): IO[RedisError, Long] = {
val command = RedisCommand(GetBit, Tuple2(ArbitraryInput[K](), LongInput), LongOutput, codec, executor)
val command = RedisCommand(GetBit, Tuple2(ArbitraryKeyInput[K](), LongInput), LongOutput, codec, executor)
command.run((key, offset))
}
......@@ -217,7 +218,7 @@ trait Strings extends RedisEnvironment {
def returning[R: Schema]: IO[RedisError, Option[R]] =
RedisCommand(
GetRange,
Tuple2(ArbitraryInput[K](), RangeInput),
Tuple2(ArbitraryKeyInput[K](), RangeInput),
OptionalOutput(ArbitraryOutput[R]()),
codec,
executor
......@@ -240,7 +241,7 @@ trait Strings extends RedisEnvironment {
def returning[R: Schema]: IO[RedisError, Option[R]] =
RedisCommand(
GetSet,
Tuple2(ArbitraryInput[K](), ArbitraryInput[V]()),
Tuple2(ArbitraryKeyInput[K](), ArbitraryValueInput[V]()),
OptionalOutput(ArbitraryOutput[R]()),
codec,
executor
......@@ -259,7 +260,7 @@ trait Strings extends RedisEnvironment {
final def getDel[K: Schema](key: K): ResultBuilder1[Option] =
new ResultBuilder1[Option] {
def returning[R: Schema]: IO[RedisError, Option[R]] =
RedisCommand(GetDel, ArbitraryInput[K](), OptionalOutput(ArbitraryOutput[R]()), codec, executor).run(key)
RedisCommand(GetDel, ArbitraryKeyInput[K](), OptionalOutput(ArbitraryOutput[R]()), codec, executor).run(key)
}
/**
......@@ -328,7 +329,7 @@ trait Strings extends RedisEnvironment {
* Returns the value of key after the increment.
*/
final def incr[K: Schema](key: K): IO[RedisError, Long] = {
val command = RedisCommand(Incr, ArbitraryInput[K](), LongOutput, codec, executor)
val command = RedisCommand(Incr, ArbitraryKeyInput[K](), LongOutput, codec, executor)
command.run(key)
}
......@@ -344,7 +345,7 @@ trait Strings extends RedisEnvironment {
*/
final def incrBy[K: Schema](key: K, increment: Long): IO[RedisError, Long] = {
val command =
RedisCommand(IncrBy, Tuple2(ArbitraryInput[K](), LongInput), LongOutput, codec, executor)
RedisCommand(IncrBy, Tuple2(ArbitraryKeyInput[K](), LongInput), LongOutput, codec, executor)
command.run((key, increment))
}
......@@ -359,7 +360,7 @@ trait Strings extends RedisEnvironment {
* Returns the value of key after the increment.
*/
final def incrByFloat[K: Schema](key: K, increment: Double): IO[RedisError, Double] = {
val command = RedisCommand(IncrByFloat, Tuple2(ArbitraryInput[K](), DoubleInput), DoubleOutput, codec, executor)
val command = RedisCommand(IncrByFloat, Tuple2(ArbitraryKeyInput[K](), DoubleInput), DoubleOutput, codec, executor)
command.run((key, increment))
}
......@@ -382,7 +383,7 @@ trait Strings extends RedisEnvironment {
val command =
RedisCommand(
MGet,
NonEmptyList(ArbitraryInput[K]()),
NonEmptyList(ArbitraryKeyInput[K]()),
ChunkOutput(OptionalOutput(ArbitraryOutput[V]())),
codec,
executor
......@@ -401,7 +402,13 @@ trait Strings extends RedisEnvironment {
*/
final def mSet[K: Schema, V: Schema](keyValue: (K, V), keyValues: (K, V)*): IO[RedisError, Unit] = {
val command =
RedisCommand(MSet, NonEmptyList(Tuple2(ArbitraryInput[K](), ArbitraryInput[V]())), UnitOutput, codec, executor)
RedisCommand(
MSet,
NonEmptyList(Tuple2(ArbitraryKeyInput[K](), ArbitraryValueInput[V]())),
UnitOutput,
codec,
executor
)
command.run((keyValue, keyValues.toList))
}
......@@ -420,7 +427,13 @@ trait Strings extends RedisEnvironment {
keyValues: (K, V)*
): IO[RedisError, Boolean] = {
val command =
RedisCommand(MSetNx, NonEmptyList(Tuple2(ArbitraryInput[K](), ArbitraryInput[V]())), BoolOutput, codec, executor)
RedisCommand(
MSetNx,
NonEmptyList(Tuple2(ArbitraryKeyInput[K](), ArbitraryValueInput[V]())),
BoolOutput,
codec,
executor
)
command.run((keyValue, keyValues.toList))
}
......@@ -442,7 +455,7 @@ trait Strings extends RedisEnvironment {
val command =
RedisCommand(
PSetEx,
Tuple3(ArbitraryInput[K](), DurationMillisecondsInput, ArbitraryInput[V]()),
Tuple3(ArbitraryKeyInput[K](), DurationMillisecondsInput, ArbitraryValueInput[V]()),
UnitOutput,
codec,
executor
......@@ -475,8 +488,8 @@ trait Strings extends RedisEnvironment {
keepTtl: Option[KeepTtl] = None
): IO[RedisError, Boolean] = {
val input = Tuple5(
ArbitraryInput[K](),
ArbitraryInput[V](),
ArbitraryKeyInput[K](),
ArbitraryValueInput[V](),
OptionalInput(DurationTtlInput),
OptionalInput(UpdateInput),
OptionalInput(KeepTtlInput)
......@@ -498,7 +511,8 @@ trait Strings extends RedisEnvironment {
* Returns the original bit value stored at offset.
*/
final def setBit[K: Schema](key: K, offset: Long, value: Boolean): IO[RedisError, Boolean] = {
val command = RedisCommand(SetBit, Tuple3(ArbitraryInput[K](), LongInput, BoolInput), BoolOutput, codec, executor)
val command =
RedisCommand(SetBit, Tuple3(ArbitraryKeyInput[K](), LongInput, BoolInput), BoolOutput, codec, executor)
command.run((key, offset, value))
}
......@@ -520,7 +534,7 @@ trait Strings extends RedisEnvironment {
val command =
RedisCommand(
SetEx,
Tuple3(ArbitraryInput[K](), DurationSecondsInput, ArbitraryInput[V]()),
Tuple3(ArbitraryKeyInput[K](), DurationSecondsInput, ArbitraryValueInput[V]()),
UnitOutput,
codec,
executor
......@@ -539,7 +553,8 @@ trait Strings extends RedisEnvironment {
* Returns 1 if the key was set. 0 if the key was not set.
*/
final def setNx[K: Schema, V: Schema](key: K, value: V): IO[RedisError, Boolean] = {
val command = RedisCommand(SetNx, Tuple2(ArbitraryInput[K](), ArbitraryInput[V]()), BoolOutput, codec, executor)
val command =
RedisCommand(SetNx, Tuple2(ArbitraryKeyInput[K](), ArbitraryValueInput[V]()), BoolOutput, codec, executor)
command.run((key, value))
}
......@@ -557,7 +572,13 @@ trait Strings extends RedisEnvironment {
*/
final def setRange[K: Schema, V: Schema](key: K, offset: Long, value: V): IO[RedisError, Long] = {
val command =
RedisCommand(SetRange, Tuple3(ArbitraryInput[K](), LongInput, ArbitraryInput[V]()), LongOutput, codec, executor)
RedisCommand(
SetRange,
Tuple3(ArbitraryKeyInput[K](), LongInput, ArbitraryValueInput[V]()),
LongOutput,
codec,
executor
)
command.run((key, offset, value))
}
......@@ -570,7 +591,7 @@ trait Strings extends RedisEnvironment {
* Returns the length of the string.
*/
final def strLen[K: Schema](key: K): IO[RedisError, Long] = {
val command = RedisCommand(StrLen, ArbitraryInput[K](), LongOutput, codec, executor)
val command = RedisCommand(StrLen, ArbitraryKeyInput[K](), LongOutput, codec, executor)
command.run(key)
}
......@@ -600,9 +621,9 @@ trait Strings extends RedisEnvironment {
val redisCommand = RedisCommand(
StrAlgoLcs,
Tuple4(
ArbitraryInput[String](),
ArbitraryInput[K](),
ArbitraryInput[K](),
ArbitraryValueInput[String](),
ArbitraryKeyInput[K](),
ArbitraryKeyInput[K](),
OptionalInput(StralgoLcsQueryTypeInput)
),
StrAlgoLcsOutput,
......
......@@ -2,6 +2,7 @@ package zio.redis
import zio._
import zio.redis.Input._
import zio.redis.RespArgument._
import zio.test.Assertion._
import zio.test._
......@@ -22,7 +23,7 @@ object InputSpec extends BaseSpec {
test("valid value") {
for {
result <- ZIO.attempt(AbsTtlInput.encode(AbsTtl))
} yield assert(result)(equalTo(respArgs("ABSTTL")))
} yield assert(result)(equalTo(RespCommand(Literal("ABSTTL"))))
}
),
suite("Address")(
......@@ -31,81 +32,81 @@ object InputSpec extends BaseSpec {
ip <- ZIO.succeed(InetAddress.getByName("127.0.0.1"))
port <- ZIO.succeed(42)
result <- ZIO.attempt(AddressInput.encode(Address(ip, port)))
} yield assert(result)(equalTo(respArgs("127.0.0.1:42")))
} yield assert(result)(equalTo(RespCommand(Unknown("127.0.0.1:42"))))
}
),
suite("Aggregate")(
test("max") {
for {
result <- ZIO.attempt(AggregateInput.encode(Aggregate.Max))
} yield assert(result)(equalTo(respArgs("AGGREGATE", "MAX")))
} yield assert(result)(equalTo(RespCommand(Literal("AGGREGATE"), Literal("MAX"))))
},
test("min") {
for {
result <- ZIO.attempt(AggregateInput.encode(Aggregate.Min))
} yield assert(result)(equalTo(respArgs("AGGREGATE", "MIN")))
} yield assert(result)(equalTo(RespCommand(Literal("AGGREGATE"), Literal("MIN"))))
},
test("sum") {
for {
result <- ZIO.attempt(AggregateInput.encode(Aggregate.Sum))
} yield assert(result)(equalTo(respArgs("AGGREGATE", "SUM")))
} yield assert(result)(equalTo(RespCommand(Literal("AGGREGATE"), Literal("SUM"))))
}
),
suite("Alpha")(
test("alpha") {
for {
result <- ZIO.attempt(AlphaInput.encode(Alpha))
} yield assert(result)(equalTo(respArgs("ALPHA")))
} yield assert(result)(equalTo(RespCommand(Literal("ALPHA"))))
}
),
suite("Auth")(
test("with empty password") {
for {
result <- ZIO.attempt(AuthInput.encode(Auth("")))
} yield assert(result)(equalTo(respArgs("AUTH", "")))
} yield assert(result)(equalTo(RespCommand(Literal("AUTH"), Value(""))))
},
test("with non-empty password") {
for {
result <- ZIO.attempt(AuthInput.encode(Auth("pass")))
} yield assert(result)(equalTo(respArgs("AUTH", "pass")))
} yield assert(result)(equalTo(RespCommand(Literal("AUTH"), Value("pass"))))
}
),
suite("Bool")(
test("true") {
for {
result <- ZIO.attempt(BoolInput.encode(true))
} yield assert(result)(equalTo(respArgs("1")))
} yield assert(result)(equalTo(RespCommand(Literal("1"))))
},
test("false") {
for {
result <- ZIO.attempt(BoolInput.encode(false))
} yield assert(result)(equalTo(respArgs("0")))
} yield assert(result)(equalTo(RespCommand(Literal("0"))))
}
),
suite("Stralgocommand")(
test("length option") {
assert(StralgoLcsQueryTypeInput.encode(StrAlgoLcsQueryType.Len))(
equalTo(respArgs("LEN"))
equalTo(RespCommand(Literal("LEN")))
)
},
test("idx option default") {
assert(StralgoLcsQueryTypeInput.encode(Idx()))(
equalTo(respArgs("IDX"))
equalTo(RespCommand(Literal("IDX")))
)
},
test("idx option with minmatchlength") {
assert(StralgoLcsQueryTypeInput.encode(Idx(minMatchLength = 2)))(
equalTo(respArgs("IDX", "MINMATCHLEN", "2"))
equalTo(RespCommand(Literal("IDX"), Literal("MINMATCHLEN"), Unknown("2")))
)
},
test("idx option with withmatchlength") {
assert(StralgoLcsQueryTypeInput.encode(Idx(withMatchLength = true)))(
equalTo(respArgs("IDX", "WITHMATCHLEN"))
equalTo(RespCommand(Literal("IDX"), Literal("WITHMATCHLEN")))
)
},
test("idx option with minmatchlength and withmatchlength") {
assert(StralgoLcsQueryTypeInput.encode(Idx(minMatchLength = 2, withMatchLength = true)))(
equalTo(respArgs("IDX", "MINMATCHLEN", "2", "WITHMATCHLEN"))
equalTo(RespCommand(Literal("IDX"), Literal("MINMATCHLEN"), Unknown("2"), Literal("WITHMATCHLEN")))
)
}
),
......@@ -113,110 +114,110 @@ object InputSpec extends BaseSpec {
test("get with unsigned type and positive offset") {
for {
result <- ZIO.attempt(BitFieldCommandInput.encode(BitFieldGet(UnsignedInt(3), 2)))
} yield assert(result)(equalTo(respArgs("GET", "u3", "2")))
} yield assert(result)(equalTo(RespCommand(Literal("GET"), Unknown("u3"), Unknown("2"))))
},
test("get with signed type and negative offset") {
for {
result <- ZIO.attempt(BitFieldCommandInput.encode(BitFieldGet(SignedInt(3), -2)))
} yield assert(result)(equalTo(respArgs("GET", "i3", "-2")))
} yield assert(result)(equalTo(RespCommand(Literal("GET"), Unknown("i3"), Unknown("-2"))))
},
test("get with unsigned type and zero offset") {
for {
result <- ZIO.attempt(BitFieldCommandInput.encode(BitFieldGet(UnsignedInt(3), 0)))
} yield assert(result)(equalTo(respArgs("GET", "u3", "0")))
} yield assert(result)(equalTo(RespCommand(Literal("GET"), Unknown("u3"), Unknown("0"))))
},
test("set with unsigned type, positive offset and positive value") {
for {
result <- ZIO.attempt(BitFieldCommandInput.encode(BitFieldSet(UnsignedInt(3), 2, 100L)))
} yield assert(result)(equalTo(respArgs("SET", "u3", "2", "100")))
} yield assert(result)(equalTo(RespCommand(Literal("SET"), Unknown("u3"), Unknown("2"), Unknown("100"))))
},
test("set with signed type, negative offset and negative value") {
for {
result <- ZIO.attempt(BitFieldCommandInput.encode(BitFieldSet(SignedInt(3), -2, -100L)))
} yield assert(result)(equalTo(respArgs("SET", "i3", "-2", "-100")))
} yield assert(result)(equalTo(RespCommand(Literal("SET"), Unknown("i3"), Unknown("-2"), Unknown("-100"))))
},
test("set with unsigned type, zero offset and zero value") {
for {
result <- ZIO.attempt(BitFieldCommandInput.encode(BitFieldSet(UnsignedInt(3), 0, 0L)))
} yield assert(result)(equalTo(respArgs("SET", "u3", "0", "0")))
} yield assert(result)(equalTo(RespCommand(Literal("SET"), Unknown("u3"), Unknown("0"), Unknown("0"))))
},
test("incr with unsigned type, positive offset and positive value") {
for {
result <- ZIO.attempt(BitFieldCommandInput.encode(BitFieldIncr(UnsignedInt(3), 2, 100L)))
} yield assert(result)(equalTo(respArgs("INCRBY", "u3", "2", "100")))
} yield assert(result)(equalTo(RespCommand(Literal("INCRBY"), Unknown("u3"), Unknown("2"), Unknown("100"))))
},
test("incr with signed type, negative offset and negative value") {
for {
result <- ZIO.attempt(BitFieldCommandInput.encode(BitFieldIncr(SignedInt(3), -2, -100L)))
} yield assert(result)(equalTo(respArgs("INCRBY", "i3", "-2", "-100")))
} yield assert(result)(equalTo(RespCommand(Literal("INCRBY"), Unknown("i3"), Unknown("-2"), Unknown("-100"))))
},
test("incr with unsigned type, zero offset and zero value") {
for {
result <- ZIO.attempt(BitFieldCommandInput.encode(BitFieldIncr(UnsignedInt(3), 0, 0L)))
} yield assert(result)(equalTo(respArgs("INCRBY", "u3", "0", "0")))
} yield assert(result)(equalTo(RespCommand(Literal("INCRBY"), Unknown("u3"), Unknown("0"), Unknown("0"))))
},
test("overflow sat") {
for {
result <- ZIO.attempt(BitFieldCommandInput.encode(BitFieldOverflow.Sat))
} yield assert(result)(equalTo(respArgs("OVERFLOW", "SAT")))
} yield assert(result)(equalTo(RespCommand(Literal("OVERFLOW"), Literal("SAT"))))
},
test("overflow fail") {
for {
result <- ZIO.attempt(BitFieldCommandInput.encode(BitFieldOverflow.Fail))
} yield assert(result)(equalTo(respArgs("OVERFLOW", "FAIL")))
} yield assert(result)(equalTo(RespCommand(Literal("OVERFLOW"), Literal("FAIL"))))
},
test("overflow warp") {
for {
result <- ZIO.attempt(BitFieldCommandInput.encode(BitFieldOverflow.Wrap))
} yield assert(result)(equalTo(respArgs("OVERFLOW", "WRAP")))
} yield assert(result)(equalTo(RespCommand(Literal("OVERFLOW"), Literal("WRAP"))))
}
),
suite("BitOperation")(
test("and") {
for {
result <- ZIO.attempt(BitOperationInput.encode(AND))
} yield assert(result)(equalTo(respArgs("AND")))
} yield assert(result)(equalTo(RespCommand(Literal("AND"))))
},
test("or") {
for {
result <- ZIO.attempt(BitOperationInput.encode(OR))
} yield assert(result)(equalTo(respArgs("OR")))
} yield assert(result)(equalTo(RespCommand(Literal("OR"))))
},
test("xor") {
for {
result <- ZIO.attempt(BitOperationInput.encode(XOR))
} yield assert(result)(equalTo(respArgs("XOR")))
} yield assert(result)(equalTo(RespCommand(Literal("XOR"))))
},
test("not") {
for {
result <- ZIO.attempt(BitOperationInput.encode(NOT))
} yield assert(result)(equalTo(respArgs("NOT")))
} yield assert(result)(equalTo(RespCommand(Literal("NOT"))))
}
),
suite("BitPosRange")(
test("with only start") {
for {
result <- ZIO.attempt(BitPosRangeInput.encode(BitPosRange(1.second.toMillis, None)))
} yield assert(result)(equalTo(respArgs("1000")))
} yield assert(result)(equalTo(RespCommand(Unknown("1000"))))
},
test("with start and the end") {
for {
result <- ZIO.attempt(BitPosRangeInput.encode(BitPosRange(0.second.toMillis, Some(1.second.toMillis))))
} yield assert(result)(equalTo(respArgs("0", "1000")))
} yield assert(result)(equalTo(RespCommand(Unknown("0"), Unknown("1000"))))
}
),
suite("By")(
test("with a pattern") {
for {
result <- ZIO.attempt(ByInput.encode("mykey_*"))
} yield assert(result)(equalTo(respArgs("BY", "mykey_*")))
} yield assert(result)(equalTo(RespCommand(Literal("BY"), Unknown("mykey_*"))))
}
),
suite("Changed")(
test("valid value") {
for {
result <- ZIO.attempt(ChangedInput.encode(Changed))
} yield assert(result)(equalTo(respArgs("CH")))
} yield assert(result)(equalTo(RespCommand(Literal("CH"))))
}
),
suite("ClientKill")(
......@@ -225,56 +226,56 @@ object InputSpec extends BaseSpec {
address <- ZIO.succeed(InetAddress.getByName("127.0.0.1"))
port <- ZIO.succeed(42)
result <- ZIO.attempt(ClientKillInput.encode(ClientKillFilter.Address(address, port)))
} yield assert(result)(equalTo(respArgs("ADDR", "127.0.0.1:42")))
} yield assert(result)(equalTo(RespCommand(Literal("ADDR"), Unknown("127.0.0.1:42"))))
},
test("local address") {
for {
address <- ZIO.succeed(InetAddress.getByName("127.0.0.1"))
port <- ZIO.succeed(42)
result <- ZIO.attempt(ClientKillInput.encode(ClientKillFilter.LocalAddress(address, port)))
} yield assert(result)(equalTo(respArgs("LADDR", s"127.0.0.1:42")))
} yield assert(result)(equalTo(RespCommand(Literal("LADDR"), Unknown(s"127.0.0.1:42"))))
},
test("client id") {
for {
id <- ZIO.succeed(42L)
result <- ZIO.attempt(ClientKillInput.encode(ClientKillFilter.Id(id)))
} yield assert(result)(equalTo(respArgs("ID", "42")))
} yield assert(result)(equalTo(RespCommand(Literal("ID"), Unknown("42"))))
},
test("type") {
for {
clientType <- ZIO.succeed(ClientType.PubSub)
result <- ZIO.attempt(ClientKillInput.encode(ClientKillFilter.Type(clientType)))
} yield assert(result)(equalTo(respArgs("TYPE", "pubsub")))
} yield assert(result)(equalTo(RespCommand(Literal("TYPE"), Literal("pubsub"))))
},
test("user") {
for {
user <- ZIO.succeed("Foo Bar")
result <- ZIO.attempt(ClientKillInput.encode(ClientKillFilter.User(user)))
} yield assert(result)(equalTo(respArgs("USER", "Foo Bar")))
} yield assert(result)(equalTo(RespCommand(Literal("USER"), Unknown("Foo Bar"))))
},
test("skip me") {
for {
result <- ZIO.attempt(ClientKillInput.encode(ClientKillFilter.SkipMe(true)))
} yield assert(result)(equalTo(respArgs("SKIPME", "YES")))
} yield assert(result)(equalTo(RespCommand(Literal("SKIPME"), Literal("YES"))))
}
),
suite("ClientPauseMode")(
test("all") {
for {
result <- ZIO.attempt(ClientPauseModeInput.encode(ClientPauseMode.All))
} yield assert(result)(equalTo(respArgs("ALL")))
} yield assert(result)(equalTo(RespCommand(Literal("ALL"))))
},
test("write") {
for {
result <- ZIO.attempt(ClientPauseModeInput.encode(ClientPauseMode.Write))
} yield assert(result)(equalTo(respArgs("WRITE")))
} yield assert(result)(equalTo(RespCommand(Literal("WRITE"))))
}
),
suite("ClientTracking")(
test("off") {
for {
result <- ZIO.attempt(ClientTrackingInput.encode(None))
} yield assert(result)(equalTo(respArgs("OFF")))
} yield assert(result)(equalTo(RespCommand(Literal("OFF"))))
},
test("client redirect with noloop and prefixes") {
for {
......@@ -283,8 +284,9 @@ object InputSpec extends BaseSpec {
result <- ZIO.attempt(ClientTrackingInput.encode(Some((Some(clientId), None, true, prefixes))))
} yield assert(result)(
equalTo(
respArgs("ON", "REDIRECT", clientId.toString) ++ prefixes
.flatMap(respArgs("PREFIX", _)) ++ respArgs("NOLOOP")
RespCommand(Literal("ON"), Literal("REDIRECT"), Unknown(clientId.toString)) ++ prefixes
.map(p => RespCommand(Literal("PREFIX"), Unknown(p)))
.fold(RespCommand.empty)(_ ++ _) ++ RespCommand(Literal("NOLOOP"))
)
)
},
......@@ -294,635 +296,635 @@ object InputSpec extends BaseSpec {
ZIO.attempt(
ClientTrackingInput.encode(Some((None, Some(ClientTrackingMode.Broadcast), false, Chunk.empty)))
)
} yield assert(result)(equalTo(respArgs("ON", "BCAST")))
} yield assert(result)(equalTo(RespCommand(Literal("ON"), Literal("BCAST"))))
}
),
suite("Copy")(
test("valid value") {
for {
result <- ZIO.attempt(CopyInput.encode(Copy))
} yield assert(result)(equalTo(respArgs("COPY")))
} yield assert(result)(equalTo(RespCommand(Literal("COPY"))))
}
),
suite("Count")(
test("positive value") {
for {
result <- ZIO.attempt(CountInput.encode(Count(3L)))
} yield assert(result)(equalTo(respArgs("COUNT", "3")))
} yield assert(result)(equalTo(RespCommand(Literal("COUNT"), Unknown("3"))))
},
test("negative value") {
for {
result <- ZIO.attempt(CountInput.encode(Count(-3L)))
} yield assert(result)(equalTo(respArgs("COUNT", "-3")))
} yield assert(result)(equalTo(RespCommand(Literal("COUNT"), Unknown("-3"))))
},
test("zero value") {
for {
result <- ZIO.attempt(CountInput.encode(Count(0L)))
} yield assert(result)(equalTo(respArgs("COUNT", "0")))
} yield assert(result)(equalTo(RespCommand(Literal("COUNT"), Unknown("0"))))
}
),
suite("Position")(
test("before") {
for {
result <- ZIO.attempt(PositionInput.encode(Position.Before))
} yield assert(result)(equalTo(respArgs("BEFORE")))
} yield assert(result)(equalTo(RespCommand(Literal("BEFORE"))))
},
test("after") {
for {
result <- ZIO.attempt(PositionInput.encode(Position.After))
} yield assert(result)(equalTo(respArgs("AFTER")))
} yield assert(result)(equalTo(RespCommand(Literal("AFTER"))))
}
),
suite("RedisType")(
test("string type") {
for {
result <- ZIO.attempt(RedisTypeInput.encode(RedisType.String))
} yield assert(result)(equalTo(respArgs("TYPE", "string")))
} yield assert(result)(equalTo(RespCommand(Literal("TYPE"), Literal("string"))))
},
test("list type") {
for {
result <- ZIO.attempt(RedisTypeInput.encode(RedisType.List))
} yield assert(result)(equalTo(respArgs("TYPE", "list")))
} yield assert(result)(equalTo(RespCommand(Literal("TYPE"), Literal("list"))))
},
test("set type") {
for {
result <- ZIO.attempt(RedisTypeInput.encode(RedisType.Set))
} yield assert(result)(equalTo(respArgs("TYPE", "set")))
} yield assert(result)(equalTo(RespCommand(Literal("TYPE"), Literal("set"))))
},
test("sorted set type") {
for {
result <- ZIO.attempt(RedisTypeInput.encode(RedisType.SortedSet))
} yield assert(result)(equalTo(respArgs("TYPE", "zset")))
} yield assert(result)(equalTo(RespCommand(Literal("TYPE"), Literal("zset"))))
},
test("hash type") {
for {
result <- ZIO.attempt(RedisTypeInput.encode(RedisType.Hash))
} yield assert(result)(equalTo(respArgs("TYPE", "hash")))
} yield assert(result)(equalTo(RespCommand(Literal("TYPE"), Literal("hash"))))
},
test("stream type") {
for {
result <- ZIO.attempt(RedisTypeInput.encode(RedisType.Stream))
} yield assert(result)(equalTo(respArgs("TYPE", "stream")))
} yield assert(result)(equalTo(RespCommand(Literal("TYPE"), Literal("stream"))))
}
),
suite("Double")(
test("positive value") {
for {
result <- ZIO.attempt(DoubleInput.encode(4.2d))
} yield assert(result)(equalTo(respArgs("4.2")))
} yield assert(result)(equalTo(RespCommand(Unknown("4.2"))))
},
test("negative value") {
for {
result <- ZIO.attempt(DoubleInput.encode(-4.2d))
} yield assert(result)(equalTo(respArgs("-4.2")))
} yield assert(result)(equalTo(RespCommand(Unknown("-4.2"))))
},
test("zero value") {
for {
result <- ZIO.attempt(DoubleInput.encode(0d))
} yield assert(result)(equalTo(respArgs("0.0")))
} yield assert(result)(equalTo(RespCommand(Unknown("0.0"))))
}
),
suite("DurationMilliseconds")(
test("1 second") {
for {
result <- ZIO.attempt(DurationMillisecondsInput.encode(1.second))
} yield assert(result)(equalTo(respArgs("1000")))
} yield assert(result)(equalTo(RespCommand(Unknown("1000"))))
},
test("100 milliseconds") {
for {
result <- ZIO.attempt(DurationMillisecondsInput.encode(100.millis))
} yield assert(result)(equalTo(respArgs("100")))
} yield assert(result)(equalTo(RespCommand(Unknown("100"))))
}
),
suite("DurationSeconds")(
test("1 minute") {
for {
result <- ZIO.attempt(DurationSecondsInput.encode(1.minute))
} yield assert(result)(equalTo(respArgs("60")))
} yield assert(result)(equalTo(RespCommand(Unknown("60"))))
},
test("1 second") {
for {
result <- ZIO.attempt(DurationSecondsInput.encode(1.second))
} yield assert(result)(equalTo(respArgs("1")))
} yield assert(result)(equalTo(RespCommand(Unknown("1"))))
},
test("100 milliseconds") {
for {
result <- ZIO.attempt(DurationSecondsInput.encode(100.millis))
} yield assert(result)(equalTo(respArgs("0")))
} yield assert(result)(equalTo(RespCommand(Unknown("0"))))
}
),
suite("DurationTtl")(
test("1 second") {
for {
result <- ZIO.attempt(DurationTtlInput.encode(1.second))
} yield assert(result)(equalTo(respArgs("PX", "1000")))
} yield assert(result)(equalTo(RespCommand(Literal("PX"), Unknown("1000"))))
},
test("100 milliseconds") {
for {
result <- ZIO.attempt(DurationTtlInput.encode(100.millis))
} yield assert(result)(equalTo(respArgs("PX", "100")))
} yield assert(result)(equalTo(RespCommand(Literal("PX"), Unknown("100"))))
}
),
suite("Freq")(
test("empty string") {
for {
result <- ZIO.attempt(FreqInput.encode(Freq("")))
} yield assert(result)(equalTo(respArgs("FREQ", "")))
} yield assert(result)(equalTo(RespCommand(Literal("FREQ"), Unknown(""))))
},
test("non-empty string") {
for {
result <- ZIO.attempt(FreqInput.encode(Freq("frequency")))
} yield assert(result)(equalTo(respArgs("FREQ", "frequency")))
} yield assert(result)(equalTo(RespCommand(Literal("FREQ"), Unknown("frequency"))))
}
),
suite("Get")(
test("with a pattern") {
for {
result <- ZIO.attempt(GetInput.encode("mypattern_*"))
} yield assert(result)(equalTo(respArgs("GET", "mypattern_*")))
} yield assert(result)(equalTo(RespCommand(Literal("GET"), Unknown("mypattern_*"))))
}
),
suite("IdleTime")(
test("0 seconds") {
for {
result <- ZIO.attempt(IdleTimeInput.encode(IdleTime(0)))
} yield assert(result)(equalTo(respArgs("IDLETIME", "0")))
} yield assert(result)(equalTo(RespCommand(Literal("IDLETIME"), Unknown("0"))))
},
test("5 seconds") {
for {
result <- ZIO.attempt(IdleTimeInput.encode(IdleTime(5)))
} yield assert(result)(equalTo(respArgs("IDLETIME", "5")))
} yield assert(result)(equalTo(RespCommand(Literal("IDLETIME"), Unknown("5"))))
}
),
suite("Increment")(
test("valid value") {
for {
result <- ZIO.attempt(IncrementInput.encode(Increment))
} yield assert(result)(equalTo(respArgs("INCR")))
} yield assert(result)(equalTo(RespCommand(Literal("INCR"))))
}
),
suite("KeepTtl")(
test("valid value") {
for {
result <- ZIO.attempt(KeepTtlInput.encode(KeepTtl))
} yield assert(result)(equalTo(respArgs("KEEPTTL")))
} yield assert(result)(equalTo(RespCommand(Literal("KEEPTTL"))))
}
),
suite("LexRange")(
test("with unbound min and unbound max") {
for {
result <- ZIO.attempt(
Tuple2(ArbitraryInput[String](), ArbitraryInput[String]())
Tuple2(ArbitraryValueInput[String](), ArbitraryValueInput[String]())
.encode((LexMinimum.Unbounded.stringify, LexMaximum.Unbounded.stringify))
)
} yield assert(result)(equalTo(respArgs("-", "+")))
} yield assert(result)(equalTo(RespCommand(Value("-"), Value("+"))))
},
test("with open min and unbound max") {
for {
result <- ZIO.attempt(
Tuple2(ArbitraryInput[String](), ArbitraryInput[String]())
Tuple2(ArbitraryValueInput[String](), ArbitraryValueInput[String]())
.encode((LexMinimum.Open("a").stringify, LexMaximum.Unbounded.stringify))
)
} yield assert(result)(equalTo(respArgs("(a", "+")))
} yield assert(result)(equalTo(RespCommand(Value("(a"), Value("+"))))
},
test("with closed min and unbound max") {
for {
result <- ZIO.attempt(
Tuple2(ArbitraryInput[String](), ArbitraryInput[String]())
Tuple2(ArbitraryValueInput[String](), ArbitraryValueInput[String]())
.encode((LexMinimum.Closed("a").stringify, LexMaximum.Unbounded.stringify))
)
} yield assert(result)(equalTo(respArgs("[a", "+")))
} yield assert(result)(equalTo(RespCommand(Value("[a"), Value("+"))))
},
test("with unbound min and open max") {
for {
result <- ZIO.attempt(
Tuple2(ArbitraryInput[String](), ArbitraryInput[String]())
Tuple2(ArbitraryValueInput[String](), ArbitraryValueInput[String]())
.encode((LexMinimum.Unbounded.stringify, LexMaximum.Open("z").stringify))
)
} yield assert(result)(equalTo(respArgs("-", "(z")))
} yield assert(result)(equalTo(RespCommand(Value("-"), Value("(z"))))
},
test("with open min and open max") {
for {
result <- ZIO.attempt(
Tuple2(ArbitraryInput[String](), ArbitraryInput[String]())
Tuple2(ArbitraryValueInput[String](), ArbitraryValueInput[String]())
.encode((LexMinimum.Open("a").stringify, LexMaximum.Open("z").stringify))
)
} yield assert(result)(equalTo(respArgs("(a", "(z")))
} yield assert(result)(equalTo(RespCommand(Value("(a"), Value("(z"))))
},
test("with closed min and open max") {
for {
result <- ZIO.attempt(
Tuple2(ArbitraryInput[String](), ArbitraryInput[String]())
Tuple2(ArbitraryValueInput[String](), ArbitraryValueInput[String]())
.encode((LexMinimum.Closed("a").stringify, LexMaximum.Open("z").stringify))
)
} yield assert(result)(equalTo(respArgs("[a", "(z")))
} yield assert(result)(equalTo(RespCommand(Value("[a"), Value("(z"))))
},
test("with unbound min and closed max") {
for {
result <- ZIO.attempt(
Tuple2(ArbitraryInput[String](), ArbitraryInput[String]())
Tuple2(ArbitraryValueInput[String](), ArbitraryValueInput[String]())
.encode((LexMinimum.Unbounded.stringify, LexMaximum.Closed("z").stringify))
)
} yield assert(result)(equalTo(respArgs("-", "[z")))
} yield assert(result)(equalTo(RespCommand(Value("-"), Value("[z"))))
},
test("with open min and closed max") {
for {
result <- ZIO.attempt(
Tuple2(ArbitraryInput[String](), ArbitraryInput[String]())
Tuple2(ArbitraryValueInput[String](), ArbitraryValueInput[String]())
.encode((LexMinimum.Open("a").stringify, LexMaximum.Closed("z").stringify))
)
} yield assert(result)(equalTo(respArgs("(a", "[z")))
} yield assert(result)(equalTo(RespCommand(Value("(a"), Value("[z"))))
},
test("with closed min and closed max") {
for {
result <- ZIO.attempt(
Tuple2(ArbitraryInput[String](), ArbitraryInput[String]())
Tuple2(ArbitraryValueInput[String](), ArbitraryValueInput[String]())
.encode((LexMinimum.Closed("a").stringify, LexMaximum.Closed("z").stringify))
)
} yield assert(result)(equalTo(respArgs("[a", "[z")))
} yield assert(result)(equalTo(RespCommand(Value("[a"), Value("[z"))))
}
),
suite("Limit")(
test("with positive offset and positive count") {
for {
result <- ZIO.attempt(LimitInput.encode(Limit(4L, 5L)))
} yield assert(result)(equalTo(respArgs("LIMIT", "4", "5")))
} yield assert(result)(equalTo(RespCommand(Literal("LIMIT"), Unknown("4"), Unknown("5"))))
},
test("with negative offset and negative count") {
for {
result <- ZIO.attempt(LimitInput.encode(Limit(-4L, -5L)))
} yield assert(result)(equalTo(respArgs("LIMIT", "-4", "-5")))
} yield assert(result)(equalTo(RespCommand(Literal("LIMIT"), Unknown("-4"), Unknown("-5"))))
},
test("with zero offset and zero count") {
for {
result <- ZIO.attempt(LimitInput.encode(Limit(0L, 0L)))
} yield assert(result)(equalTo(respArgs("LIMIT", "0", "0")))
} yield assert(result)(equalTo(RespCommand(Literal("LIMIT"), Unknown("0"), Unknown("0"))))
}
),
suite("Long")(
test("positive value") {
for {
result <- ZIO.attempt(LongInput.encode(4L))
} yield assert(result)(equalTo(respArgs("4")))
} yield assert(result)(equalTo(RespCommand(Unknown("4"))))
},
test("negative value") {
for {
result <- ZIO.attempt(LongInput.encode(-4L))
} yield assert(result)(equalTo(respArgs("-4")))
} yield assert(result)(equalTo(RespCommand(Unknown("-4"))))
},
test("zero value") {
for {
result <- ZIO.attempt(LongInput.encode(0L))
} yield assert(result)(equalTo(respArgs("0")))
} yield assert(result)(equalTo(RespCommand(Unknown("0"))))
}
),
suite("LongLat")(
test("positive longitude and latitude") {
for {
result <- ZIO.attempt(LongLatInput.encode(LongLat(4.2d, 5.2d)))
} yield assert(result)(equalTo(respArgs("4.2", "5.2")))
} yield assert(result)(equalTo(RespCommand(Unknown("4.2"), Unknown("5.2"))))
},
test("negative longitude and latitude") {
for {
result <- ZIO.attempt(LongLatInput.encode(LongLat(-4.2d, -5.2d)))
} yield assert(result)(equalTo(respArgs("-4.2", "-5.2")))
} yield assert(result)(equalTo(RespCommand(Unknown("-4.2"), Unknown("-5.2"))))
},
test("zero longitude and latitude") {
for {
result <- ZIO.attempt(LongLatInput.encode(LongLat(0d, 0d)))
} yield assert(result)(equalTo(respArgs("0.0", "0.0")))
} yield assert(result)(equalTo(RespCommand(Unknown("0.0"), Unknown("0.0"))))
}
),
suite("MemberScore")(
test("with positive score and empty member") {
for {
result <- ZIO.attempt(MemberScoreInput[String]().encode(MemberScore(4.2d, "")))
} yield assert(result)(equalTo(respArgs("4.2", "")))
} yield assert(result)(equalTo(RespCommand(Unknown("4.2"), Value(""))))
},
test("with negative score and empty member") {
for {
result <- ZIO.attempt(MemberScoreInput[String]().encode(MemberScore(-4.2d, "")))
} yield assert(result)(equalTo(respArgs("-4.2", "")))
} yield assert(result)(equalTo(RespCommand(Unknown("-4.2"), Value(""))))
},
test("with zero score and empty member") {
for {
result <- ZIO.attempt(MemberScoreInput[String]().encode(MemberScore(0d, "")))
} yield assert(result)(equalTo(respArgs("0.0", "")))
} yield assert(result)(equalTo(RespCommand(Unknown("0.0"), Value(""))))
},
test("with positive score and non-empty member") {
for {
result <- ZIO.attempt(MemberScoreInput[String]().encode(MemberScore(4.2d, "member")))
} yield assert(result)(equalTo(respArgs("4.2", "member")))
} yield assert(result)(equalTo(RespCommand(Unknown("4.2"), Value("member"))))
},
test("with negative score and non-empty member") {
for {
result <- ZIO.attempt(MemberScoreInput[String]().encode(MemberScore(-4.2d, "member")))
} yield assert(result)(equalTo(respArgs("-4.2", "member")))
} yield assert(result)(equalTo(RespCommand(Unknown("-4.2"), Value("member"))))
},
test("with zero score and non-empty member") {
for {
result <- ZIO.attempt(MemberScoreInput[String]().encode(MemberScore(0d, "member")))
} yield assert(result)(equalTo(respArgs("0.0", "member")))
} yield assert(result)(equalTo(RespCommand(Unknown("0.0"), Value("member"))))
}
),
suite("NoInput")(
test("valid value") {
for {
result <- ZIO.attempt(NoInput.encode(()))
} yield assert(result)(isEmpty)
} yield assert(result.args)(isEmpty)
}
),
suite("NonEmptyList")(
test("with multiple elements") {
for {
result <- ZIO.attempt(NonEmptyList(StringInput).encode(("a", List("b", "c"))))
} yield assert(result)(equalTo(respArgs("a", "b", "c")))
} yield assert(result)(equalTo(RespCommand(Unknown("a"), Unknown("b"), Unknown("c"))))
},
test("with one element") {
for {
result <- ZIO.attempt(NonEmptyList(StringInput).encode(("a", List.empty)))
} yield assert(result)(equalTo(respArgs("a")))
} yield assert(result)(equalTo(RespCommand(Unknown("a"))))
}
),
suite("Order")(
test("ascending") {
for {
result <- ZIO.attempt(OrderInput.encode(Ascending))
} yield assert(result)(equalTo(respArgs("ASC")))
} yield assert(result)(equalTo(RespCommand(Unknown("ASC"))))
},
test("descending") {
for {
result <- ZIO.attempt(OrderInput.encode(Descending))
} yield assert(result)(equalTo(respArgs("DESC")))
} yield assert(result)(equalTo(RespCommand(Unknown("DESC"))))
}
),
suite("RadiusUnit")(
test("meters") {
for {
result <- ZIO.attempt(RadiusUnitInput.encode(Meters))
} yield assert(result)(equalTo(respArgs("m")))
} yield assert(result)(equalTo(RespCommand(Unknown("m"))))
},
test("kilometers") {
for {
result <- ZIO.attempt(RadiusUnitInput.encode(Kilometers))
} yield assert(result)(equalTo(respArgs("km")))
} yield assert(result)(equalTo(RespCommand(Unknown("km"))))
},
test("feet") {
for {
result <- ZIO.attempt(RadiusUnitInput.encode(Feet))
} yield assert(result)(equalTo(respArgs("ft")))
} yield assert(result)(equalTo(RespCommand(Unknown("ft"))))
},
test("miles") {
for {
result <- ZIO.attempt(RadiusUnitInput.encode(Miles))
} yield assert(result)(equalTo(respArgs("mi")))
} yield assert(result)(equalTo(RespCommand(Unknown("mi"))))
}
),
suite("Range")(
test("with positive start and positive end") {
for {
result <- ZIO.attempt(RangeInput.encode(Range(1, 5)))
} yield assert(result)(equalTo(respArgs("1", "5")))
} yield assert(result)(equalTo(RespCommand(Unknown("1"), Unknown("5"))))
},
test("with negative start and positive end") {
for {
result <- ZIO.attempt(RangeInput.encode(Range(-1, 5)))
} yield assert(result)(equalTo(respArgs("-1", "5")))
} yield assert(result)(equalTo(RespCommand(Unknown("-1"), Unknown("5"))))
},
test("with positive start and negative end") {
for {
result <- ZIO.attempt(RangeInput.encode(Range(1, -5)))
} yield assert(result)(equalTo(respArgs("1", "-5")))
} yield assert(result)(equalTo(RespCommand(Unknown("1"), Unknown("-5"))))
},
test("with negative start and negative end") {
for {
result <- ZIO.attempt(RangeInput.encode(Range(-1, -5)))
} yield assert(result)(equalTo(respArgs("-1", "-5")))
} yield assert(result)(equalTo(RespCommand(Unknown("-1"), Unknown("-5"))))
}
),
suite("Pattern")(
test("with valid pattern") {
for {
result <- ZIO.attempt(PatternInput.encode(Pattern("*[ab]-*")))
} yield assert(result)(equalTo(respArgs("MATCH", "*[ab]-*")))
} yield assert(result)(equalTo(RespCommand(Literal("MATCH"), Unknown("*[ab]-*"))))
},
test("with empty pattern") {
for {
result <- ZIO.attempt(PatternInput.encode(Pattern("")))
} yield assert(result)(equalTo(respArgs("MATCH", "")))
} yield assert(result)(equalTo(RespCommand(Literal("MATCH"), Unknown(""))))
}
),
suite("Replace")(
test("valid value") {
for {
result <- ZIO.attempt(ReplaceInput.encode(Replace))
} yield assert(result)(equalTo(respArgs("REPLACE")))
} yield assert(result)(equalTo(RespCommand(Literal("REPLACE"))))
}
),
suite("StoreDist")(
test("with non-empty string") {
for {
result <- ZIO.attempt(StoreDistInput.encode(StoreDist("key")))
} yield assert(result)(equalTo(respArgs("STOREDIST", "key")))
} yield assert(result)(equalTo(RespCommand(Literal("STOREDIST"), Unknown("key"))))
},
test("with empty string") {
for {
result <- ZIO.attempt(StoreDistInput.encode(StoreDist("")))
} yield assert(result)(equalTo(respArgs("STOREDIST", "")))
} yield assert(result)(equalTo(RespCommand(Literal("STOREDIST"), Unknown(""))))
}
),
suite("Store")(
test("with non-empty string") {
for {
result <- ZIO.attempt(StoreInput.encode(Store("key")))
} yield assert(result)(equalTo(respArgs("STORE", "key")))
} yield assert(result)(equalTo(RespCommand(Literal("STORE"), Unknown("key"))))
},
test("with empty string") {
for {
result <- ZIO.attempt(StoreInput.encode(Store("")))
} yield assert(result)(equalTo(respArgs("STORE", "")))
} yield assert(result)(equalTo(RespCommand(Literal("STORE"), Unknown(""))))
}
),
suite("ScoreRange")(
test("with infinite min and infinite max") {
for {
result <- ZIO.attempt(
Tuple2(ArbitraryInput[String](), ArbitraryInput[String]())
Tuple2(ArbitraryValueInput[String](), ArbitraryValueInput[String]())
.encode((ScoreMinimum.Infinity.stringify, ScoreMaximum.Infinity.stringify))
)
} yield assert(result)(equalTo(respArgs("-inf", "+inf")))
} yield assert(result)(equalTo(RespCommand(Value("-inf"), Value("+inf"))))
},
test("with open min and infinite max") {
for {
result <- ZIO.attempt(
Tuple2(ArbitraryInput[String](), ArbitraryInput[String]())
Tuple2(ArbitraryValueInput[String](), ArbitraryValueInput[String]())
.encode((ScoreMinimum.Open(4.2d).stringify, ScoreMaximum.Infinity.stringify))
)
} yield assert(result)(equalTo(respArgs("(4.2", "+inf")))
} yield assert(result)(equalTo(RespCommand(Value("(4.2"), Value("+inf"))))
},
test("with closed min and infinite max") {
for {
result <- ZIO.attempt(
Tuple2(ArbitraryInput[String](), ArbitraryInput[String]())
Tuple2(ArbitraryValueInput[String](), ArbitraryValueInput[String]())
.encode((ScoreMinimum.Closed(4.2d).stringify, ScoreMaximum.Infinity.stringify))
)
} yield assert(result)(equalTo(respArgs("4.2", "+inf")))
} yield assert(result)(equalTo(RespCommand(Value("4.2"), Value("+inf"))))
},
test("with infinite min and open max") {
for {
result <- ZIO.attempt(
Tuple2(ArbitraryInput[String](), ArbitraryInput[String]())
Tuple2(ArbitraryValueInput[String](), ArbitraryValueInput[String]())
.encode((ScoreMinimum.Infinity.stringify, ScoreMaximum.Open(5.2d).stringify))
)
} yield assert(result)(equalTo(respArgs("-inf", "(5.2")))
} yield assert(result)(equalTo(RespCommand(Value("-inf"), Value("(5.2"))))
},
test("with open min and open max") {
for {
result <- ZIO.attempt(
Tuple2(ArbitraryInput[String](), ArbitraryInput[String]())
Tuple2(ArbitraryValueInput[String](), ArbitraryValueInput[String]())
.encode((ScoreMinimum.Open(4.2d).stringify, ScoreMaximum.Open(5.2d).stringify))
)
} yield assert(result)(equalTo(respArgs("(4.2", "(5.2")))
} yield assert(result)(equalTo(RespCommand(Value("(4.2"), Value("(5.2"))))
},
test("with closed min and open max") {
for {
result <- ZIO.attempt(
Tuple2(ArbitraryInput[String](), ArbitraryInput[String]())
Tuple2(ArbitraryValueInput[String](), ArbitraryValueInput[String]())
.encode((ScoreMinimum.Closed(4.2d).stringify, ScoreMaximum.Open(5.2d).stringify))
)
} yield assert(result)(equalTo(respArgs("4.2", "(5.2")))
} yield assert(result)(equalTo(RespCommand(Value("4.2"), Value("(5.2"))))
},
test("with infinite min and closed max") {
for {
result <- ZIO.attempt(
Tuple2(ArbitraryInput[String](), ArbitraryInput[String]())
Tuple2(ArbitraryValueInput[String](), ArbitraryValueInput[String]())
.encode((ScoreMinimum.Infinity.stringify, ScoreMaximum.Closed(5.2d).stringify))
)
} yield assert(result)(equalTo(respArgs("-inf", "5.2")))
} yield assert(result)(equalTo(RespCommand(Value("-inf"), Value("5.2"))))
},
test("with open min and closed max") {
for {
result <- ZIO.attempt(
Tuple2(ArbitraryInput[String](), ArbitraryInput[String]())
Tuple2(ArbitraryValueInput[String](), ArbitraryValueInput[String]())
.encode((ScoreMinimum.Open(4.2d).stringify, ScoreMaximum.Closed(5.2d).stringify))
)
} yield assert(result)(equalTo(respArgs("(4.2", "5.2")))
} yield assert(result)(equalTo(RespCommand(Value("(4.2"), Value("5.2"))))
},
test("with closed min and closed max") {
for {
result <- ZIO.attempt(
Tuple2(ArbitraryInput[String](), ArbitraryInput[String]())
Tuple2(ArbitraryValueInput[String](), ArbitraryValueInput[String]())
.encode((ScoreMinimum.Closed(4.2d).stringify, ScoreMaximum.Closed(5.2d).stringify))
)
} yield assert(result)(equalTo(respArgs("4.2", "5.2")))
} yield assert(result)(equalTo(RespCommand(Value("4.2"), Value("5.2"))))
}
),
suite("ScriptDebug")(
test("yes") {
for {
result <- ZIO.attempt(ScriptDebugInput.encode(DebugMode.Yes))
} yield assert(result)(equalTo(respArgs("YES")))
} yield assert(result)(equalTo(RespCommand(Literal("YES"))))
},
test("sync") {
for {
result <- ZIO.attempt(ScriptDebugInput.encode(DebugMode.Sync))
} yield assert(result)(equalTo(respArgs("SYNC")))
} yield assert(result)(equalTo(RespCommand(Literal("SYNC"))))
},
test("no") {
for {
result <- ZIO.attempt(ScriptDebugInput.encode(DebugMode.No))
} yield assert(result)(equalTo(respArgs("NO")))
} yield assert(result)(equalTo(RespCommand(Literal("NO"))))
}
),
suite("ScriptFlush")(
test("asynchronous") {
for {
result <- ZIO.attempt(ScriptFlushInput.encode(FlushMode.Async))
} yield assert(result)(equalTo(respArgs("ASYNC")))
} yield assert(result)(equalTo(RespCommand(Literal("ASYNC"))))
},
test("synchronous") {
for {
result <- ZIO.attempt(ScriptFlushInput.encode(FlushMode.Sync))
} yield assert(result)(equalTo(respArgs("SYNC")))
} yield assert(result)(equalTo(RespCommand(Literal("SYNC"))))
}
),
suite("String")(
test("non-empty value") {
for {
result <- ZIO.attempt(StringInput.encode("non-empty"))
} yield assert(result)(equalTo(respArgs("non-empty")))
} yield assert(result)(equalTo(RespCommand(Unknown("non-empty"))))
},
test("empty value") {
for {
result <- ZIO.attempt(StringInput.encode(""))
} yield assert(result)(equalTo(respArgs("")))
} yield assert(result)(equalTo(RespCommand(Unknown(""))))
}
),
suite("Optional")(
test("none") {
for {
result <- ZIO.attempt(OptionalInput(LongInput).encode(None))
} yield assert(result)(isEmpty)
} yield assert(result.args)(isEmpty)
},
test("some") {
for {
result <- ZIO.attempt(OptionalInput(LongInput).encode(Some(2L)))
} yield assert(result)(equalTo(respArgs("2")))
} yield assert(result)(equalTo(RespCommand(Unknown("2"))))
}
),
suite("TimeSeconds")(
test("positiv value") {
for {
result <- ZIO.attempt(TimeSecondsInput.encode(Instant.ofEpochSecond(3L)))
} yield assert(result)(equalTo(respArgs("3")))
} yield assert(result)(equalTo(RespCommand(Unknown("3"))))
},
test("zero value") {
for {
result <- ZIO.attempt(TimeSecondsInput.encode(Instant.ofEpochSecond(0L)))
} yield assert(result)(equalTo(respArgs("0")))
} yield assert(result)(equalTo(RespCommand(Unknown("0"))))
},
test("negative value") {
for {
result <- ZIO.attempt(TimeSecondsInput.encode(Instant.ofEpochSecond(-3L)))
} yield assert(result)(equalTo(respArgs("-3")))
} yield assert(result)(equalTo(RespCommand(Unknown("-3"))))
}
),
suite("TimeMilliseconds")(
test("positiv value") {
for {
result <- ZIO.attempt(TimeMillisecondsInput.encode(Instant.ofEpochSecond(3L)))
} yield assert(result)(equalTo(respArgs("3000")))
} yield assert(result)(equalTo(RespCommand(Unknown("3000"))))
},
test("zero value") {
for {
result <- ZIO.attempt(TimeMillisecondsInput.encode(Instant.ofEpochSecond(0L)))
} yield assert(result)(equalTo(respArgs("0")))
} yield assert(result)(equalTo(RespCommand(Unknown("0"))))
},
test("negative value") {
for {
result <- ZIO.attempt(TimeMillisecondsInput.encode(Instant.ofEpochSecond(-3L)))
} yield assert(result)(equalTo(respArgs("-3000")))
} yield assert(result)(equalTo(RespCommand(Unknown("-3000"))))
}
),
suite("Tuple2")(
test("valid value") {
for {
result <- ZIO.attempt(Tuple2(StringInput, LongInput).encode(("one", 2L)))
} yield assert(result)(equalTo(respArgs("one", "2")))
} yield assert(result)(equalTo(RespCommand(Unknown("one"), Unknown("2"))))
}
),
suite("Tuple3")(
test("valid value") {
for {
result <- ZIO.attempt(Tuple3(StringInput, LongInput, StringInput).encode(("one", 2, "three")))
} yield assert(result)(equalTo(respArgs("one", "2", "three")))
} yield assert(result)(equalTo(RespCommand(Unknown("one"), Unknown("2"), Unknown("three"))))
}
),
suite("Tuple4")(
test("valid value") {
for {
result <- ZIO.attempt(Tuple4(StringInput, LongInput, StringInput, LongInput).encode(("one", 2, "three", 4)))
} yield assert(result)(equalTo(respArgs("one", "2", "three", "4")))
} yield assert(result)(equalTo(RespCommand(Unknown("one"), Unknown("2"), Unknown("three"), Unknown("4"))))
}
),
suite("Tuple5")(
......@@ -933,7 +935,7 @@ object InputSpec extends BaseSpec {
.encode(("one", 2, "three", 4, "five"))
)
} yield assert(result)(
equalTo(respArgs("one", "2", "three", "4", "five"))
equalTo(RespCommand(Unknown("one"), Unknown("2"), Unknown("three"), Unknown("4"), Unknown("five")))
)
}
),
......@@ -946,14 +948,14 @@ object InputSpec extends BaseSpec {
)
} yield assert(result)(
equalTo(
respArgs(
"one",
"2",
"three",
"4",
"five",
"6",
"seven"
RespCommand(
Unknown("one"),
Unknown("2"),
Unknown("three"),
Unknown("4"),
Unknown("five"),
Unknown("6"),
Unknown("seven")
)
)
)
......@@ -977,16 +979,16 @@ object InputSpec extends BaseSpec {
)
} yield assert(result)(
equalTo(
respArgs(
"one",
"2",
"three",
"4",
"five",
"6",
"seven",
"8",
"nine"
RespCommand(
Unknown("one"),
Unknown("2"),
Unknown("three"),
Unknown("4"),
Unknown("five"),
Unknown("6"),
Unknown("seven"),
Unknown("8"),
Unknown("nine")
)
)
)
......@@ -1012,18 +1014,18 @@ object InputSpec extends BaseSpec {
)
} yield assert(result)(
equalTo(
respArgs(
"one",
"2",
"three",
"4",
"five",
"6",
"seven",
"8",
"nine",
"10",
"eleven"
RespCommand(
Unknown("one"),
Unknown("2"),
Unknown("three"),
Unknown("4"),
Unknown("five"),
Unknown("6"),
Unknown("seven"),
Unknown("8"),
Unknown("nine"),
Unknown("10"),
Unknown("eleven")
)
)
)
......@@ -1033,117 +1035,117 @@ object InputSpec extends BaseSpec {
test("set existing") {
for {
result <- ZIO.attempt(UpdateInput.encode(Update.SetExisting))
} yield assert(result)(equalTo(respArgs("XX")))
} yield assert(result)(equalTo(RespCommand(Unknown("XX"))))
},
test("set new") {
for {
result <- ZIO.attempt(UpdateInput.encode(Update.SetNew))
} yield assert(result)(equalTo(respArgs("NX")))
} yield assert(result)(equalTo(RespCommand(Unknown("NX"))))
}
),
suite("Id")(
test("valid value") {
for {
result <- ZIO.attempt(IdInput.encode(10))
} yield assert(result)(equalTo(respArgs("ID", "10")))
} yield assert(result)(equalTo(RespCommand(Literal("ID"), Unknown("10"))))
}
),
suite("UnblockBehavior")(
test("timeout") {
for {
result <- ZIO.attempt(UnblockBehaviorInput.encode(UnblockBehavior.Timeout))
} yield assert(result)(equalTo(respArgs("TIMEOUT")))
} yield assert(result)(equalTo(RespCommand(Unknown("TIMEOUT"))))
},
test("error") {
for {
result <- ZIO.attempt(UnblockBehaviorInput.encode(UnblockBehavior.Error))
} yield assert(result)(equalTo(respArgs("ERROR")))
} yield assert(result)(equalTo(RespCommand(Unknown("ERROR"))))
}
),
suite("Varargs")(
test("with multiple elements") {
for {
result <- ZIO.attempt(Varargs(LongInput).encode(List(1, 2, 3)))
} yield assert(result)(equalTo(respArgs("1", "2", "3")))
} yield assert(result)(equalTo(RespCommand(Unknown("1"), Unknown("2"), Unknown("3"))))
},
test("with no elements") {
for {
result <- ZIO.attempt(Varargs(LongInput).encode(List.empty))
} yield assert(result)(isEmpty)
} yield assert(result.args)(isEmpty)
}
),
suite("WithScores")(
test("valid value") {
for {
result <- ZIO.attempt(WithScoresInput.encode(WithScores))
} yield assert(result)(equalTo(respArgs("WITHSCORES")))
} yield assert(result)(equalTo(RespCommand(Literal("WITHSCORES"))))
}
),
suite("WithCoord")(
test("valid value") {
for {
result <- ZIO.attempt(WithCoordInput.encode(WithCoord))
} yield assert(result)(equalTo(respArgs("WITHCOORD")))
} yield assert(result)(equalTo(RespCommand(Literal("WITHCOORD"))))
}
),
suite("WithDist")(
test("valid value") {
for {
result <- ZIO.attempt(WithDistInput.encode(WithDist))
} yield assert(result)(equalTo(respArgs("WITHDIST")))
} yield assert(result)(equalTo(RespCommand(Literal("WITHDIST"))))
}
),
suite("WithHash")(
test("valid value") {
for {
result <- ZIO.attempt(WithHashInput.encode(WithHash))
} yield assert(result)(equalTo(respArgs("WITHHASH")))
} yield assert(result)(equalTo(RespCommand(Literal("WITHHASH"))))
}
),
suite("Idle")(
test("with 1 second") {
ZIO
.attempt(IdleInput.encode(1.second))
.map(assert(_)(equalTo(respArgs("IDLE", "1000"))))
.map(assert(_)(equalTo(RespCommand(Literal("IDLE"), Unknown("1000")))))
},
test("with 100 milliseconds") {
ZIO
.attempt(IdleInput.encode(100.millis))
.map(assert(_)(equalTo(respArgs("IDLE", "100"))))
.map(assert(_)(equalTo(RespCommand(Literal("IDLE"), Unknown("100")))))
},
test("with negative duration") {
ZIO
.attempt(IdleInput.encode((-1).second))
.map(assert(_)(equalTo(respArgs("IDLE", "-1000"))))
.map(assert(_)(equalTo(RespCommand(Literal("IDLE"), Unknown("-1000")))))
}
),
suite("Time")(
test("with 1 second") {
ZIO
.attempt(TimeInput.encode(1.second))
.map(assert(_)(equalTo(respArgs("TIME", "1000"))))
.map(assert(_)(equalTo(RespCommand(Literal("TIME"), Unknown("1000")))))
},
test("with 100 milliseconds") {
ZIO
.attempt(TimeInput.encode(100.millis))
.map(assert(_)(equalTo(respArgs("TIME", "100"))))
.map(assert(_)(equalTo(RespCommand(Literal("TIME"), Unknown("100")))))
},
test("with negative duration") {
ZIO
.attempt(TimeInput.encode((-1).second))
.map(assert(_)(equalTo(respArgs("TIME", "-1000"))))
.map(assert(_)(equalTo(RespCommand(Literal("TIME"), Unknown("-1000")))))
}
),
suite("RetryCount")(
test("with positive count") {
ZIO
.attempt(RetryCountInput.encode(100))
.map(assert(_)(equalTo(respArgs("RETRYCOUNT", "100"))))
.map(assert(_)(equalTo(RespCommand(Literal("RETRYCOUNT"), Unknown("100")))))
},
test("with negative count") {
ZIO
.attempt(RetryCountInput.encode(-100))
.map(assert(_)(equalTo(respArgs("RETRYCOUNT", "-100"))))
.map(assert(_)(equalTo(RespCommand(Literal("RETRYCOUNT"), Unknown("-100")))))
}
),
suite("XGroupCreate")(
......@@ -1154,7 +1156,7 @@ object InputSpec extends BaseSpec {
XGroupCommand.Create("key", "group", "id", mkStream = false)
)
)
.map(assert(_)(equalTo(respArgs("CREATE", "key", "group", "id"))))
.map(assert(_)(equalTo(RespCommand(Literal("CREATE"), Key("key"), Unknown("group"), Unknown("id")))))
},
test("with mkStream") {
ZIO
......@@ -1163,21 +1165,27 @@ object InputSpec extends BaseSpec {
XGroupCommand.Create("key", "group", "id", mkStream = true)
)
)
.map(assert(_)(equalTo(respArgs("CREATE", "key", "group", "id", "MKSTREAM"))))
.map(
assert(_)(
equalTo(
RespCommand(Literal("CREATE"), Key("key"), Unknown("group"), Unknown("id"), Literal("MKSTREAM"))
)
)
)
}
),
suite("XGroupSetId")(
test("valid value") {
ZIO
.attempt(XGroupSetIdInput[String, String, String]().encode(XGroupCommand.SetId("key", "group", "id")))
.map(assert(_)(equalTo(respArgs("SETID", "key", "group", "id"))))
.map(assert(_)(equalTo(RespCommand(Literal("SETID"), Key("key"), Unknown("group"), Unknown("id")))))
}
),
suite("XGroupDestroy")(
test("valid value") {
ZIO
.attempt(XGroupDestroyInput[String, String]().encode(XGroupCommand.Destroy("key", "group")))
.map(assert(_)(equalTo(respArgs("DESTROY", "key", "group"))))
.map(assert(_)(equalTo(RespCommand(Literal("DESTROY"), Key("key"), Unknown("group")))))
}
),
suite("XGroupCreateConsumer")(
......@@ -1188,7 +1196,11 @@ object InputSpec extends BaseSpec {
XGroupCommand.CreateConsumer("key", "group", "consumer")
)
)
.map(assert(_)(equalTo(respArgs("CREATECONSUMER", "key", "group", "consumer"))))
.map(
assert(_)(
equalTo(RespCommand(Literal("CREATECONSUMER"), Key("key"), Unknown("group"), Unknown("consumer")))
)
)
}
),
suite("XGroupDelConsumer")(
......@@ -1199,85 +1211,89 @@ object InputSpec extends BaseSpec {
XGroupCommand.DelConsumer("key", "group", "consumer")
)
)
.map(assert(_)(equalTo(respArgs("DELCONSUMER", "key", "group", "consumer"))))
.map(
assert(_)(equalTo(RespCommand(Literal("DELCONSUMER"), Key("key"), Unknown("group"), Unknown("consumer"))))
)
}
),
suite("Block")(
test("with 1 second") {
ZIO
.attempt(BlockInput.encode(1.second))
.map(assert(_)(equalTo(respArgs("BLOCK", "1000"))))
.map(assert(_)(equalTo(RespCommand(Literal("BLOCK"), Unknown("1000")))))
},
test("with 100 milliseconds") {
ZIO
.attempt(BlockInput.encode(100.millis))
.map(assert(_)(equalTo(respArgs("BLOCK", "100"))))
.map(assert(_)(equalTo(RespCommand(Literal("BLOCK"), Unknown("100")))))
},
test("with negative duration") {
ZIO
.attempt(BlockInput.encode((-1).second))
.map(assert(_)(equalTo(respArgs("BLOCK", "-1000"))))
.map(assert(_)(equalTo(RespCommand(Literal("BLOCK"), Unknown("-1000")))))
}
),
suite("Streams")(
test("with one pair") {
ZIO
.attempt(StreamsInput[String, String]().encode(("a" -> "b", Chunk.empty)))
.map(assert(_)(equalTo(respArgs("STREAMS", "a", "b"))))
.map(assert(_)(equalTo(RespCommand(Literal("STREAMS"), Key("a"), Value("b")))))
},
test("with multiple pairs") {
ZIO
.attempt(StreamsInput[String, String]().encode(("a" -> "b", Chunk.single("c" -> "d"))))
.map(assert(_)(equalTo(respArgs("STREAMS", "a", "c", "b", "d"))))
.map(assert(_)(equalTo(RespCommand(Literal("STREAMS"), Key("a"), Key("c"), Value("b"), Value("d")))))
}
),
suite("NoAck")(
test("valid value") {
ZIO.attempt(NoAckInput.encode(NoAck)).map(assert(_)(equalTo(respArgs("NOACK"))))
ZIO.attempt(NoAckInput.encode(NoAck)).map(assert(_)(equalTo(RespCommand(Unknown("NOACK")))))
}
),
suite("MaxLen")(
test("with approximate") {
ZIO
.attempt(StreamMaxLenInput.encode(StreamMaxLen(approximate = true, 10)))
.map(assert(_)(equalTo(respArgs("MAXLEN", "~", "10"))))
.map(assert(_)(equalTo(RespCommand(Literal("MAXLEN"), Literal("~"), Unknown("10")))))
},
test("without approximate") {
ZIO
.attempt(StreamMaxLenInput.encode(StreamMaxLen(approximate = false, 10)))
.map(assert(_)(equalTo(respArgs("MAXLEN", "10"))))
.map(assert(_)(equalTo(RespCommand(Literal("MAXLEN"), Unknown("10")))))
}
),
suite("WithForce")(
test("valid value") {
ZIO.attempt(WithForceInput.encode(WithForce)).map(assert(_)(equalTo(respArgs("FORCE"))))
ZIO.attempt(WithForceInput.encode(WithForce)).map(assert(_)(equalTo(RespCommand(Literal("FORCE")))))
}
),
suite("WithJustId")(
test("valid value") {
ZIO.attempt(WithJustIdInput.encode(WithJustId)).map(assert(_)(equalTo(respArgs("JUSTID"))))
ZIO.attempt(WithJustIdInput.encode(WithJustId)).map(assert(_)(equalTo(RespCommand(Literal("JUSTID")))))
}
),
suite("Side")(
test("left") {
for {
result <- ZIO.attempt(SideInput.encode(Side.Left))
} yield assert(result)(equalTo(respArgs("LEFT")))
} yield assert(result)(equalTo(RespCommand(Literal("LEFT"))))
},
test("right") {
for {
result <- ZIO.attempt(SideInput.encode(Side.Right))
} yield assert(result)(equalTo(respArgs("RIGHT")))
} yield assert(result)(equalTo(RespCommand(Literal("RIGHT"))))
}
),
suite("ListMaxLen")(
test("valid value") {
ZIO.attempt(ListMaxLenInput.encode(ListMaxLen(10L))).map(assert(_)(equalTo(respArgs("MAXLEN", "10"))))
ZIO
.attempt(ListMaxLenInput.encode(ListMaxLen(10L)))
.map(assert(_)(equalTo(RespCommand(Literal("MAXLEN"), Unknown("10")))))
}
),
suite("Rank")(
test("valid value") {
ZIO.attempt(RankInput.encode(Rank(10L))).map(assert(_)(equalTo(respArgs("RANK", "10"))))
ZIO.attempt(RankInput.encode(Rank(10L))).map(assert(_)(equalTo(RespCommand(Literal("RANK"), Unknown("10")))))
}
),
suite("GetEx")(
......@@ -1287,8 +1303,10 @@ object InputSpec extends BaseSpec {
ZIO.attempt(GetExInput[String]().encode(scala.Tuple3.apply("key", Expire.SetExpireSeconds, 1.second)))
resultMilliseconds <-
ZIO.attempt(GetExInput[String]().encode(scala.Tuple3("key", Expire.SetExpireMilliseconds, 100.millis)))
} yield assert(resultSeconds)(equalTo(respArgs("key", "EX", "1"))) && assert(resultMilliseconds)(
equalTo(respArgs("key", "PX", "100"))
} yield assert(resultSeconds)(equalTo(RespCommand(Key("key"), Literal("EX"), Unknown("1")))) && assert(
resultMilliseconds
)(
equalTo(RespCommand(Key("key"), Literal("PX"), Unknown("100")))
)
},
test("GetExAtInput - valid value") {
......@@ -1305,31 +1323,31 @@ object InputSpec extends BaseSpec {
scala.Tuple3("key", ExpiredAt.SetExpireAtMilliseconds, Instant.parse("2021-04-06T00:00:00Z"))
)
)
} yield assert(resultSeconds)(equalTo(respArgs("key", "EXAT", "1617667200"))) && assert(resultMilliseconds)(
equalTo(respArgs("key", "PXAT", "1617667200000"))
} yield assert(resultSeconds)(
equalTo(RespCommand(Key("key"), Literal("EXAT"), Unknown("1617667200")))
) && assert(resultMilliseconds)(
equalTo(RespCommand(Key("key"), Literal("PXAT"), Unknown("1617667200000")))
)
},
test("GetExPersistInput - valid value") {
for {
result <- ZIO.attempt(GetExPersistInput[String]().encode("key" -> true))
resultWithoutOption <- ZIO.attempt(GetExPersistInput[String]().encode("key" -> false))
} yield assert(result)(equalTo(respArgs("key", "PERSIST"))) &&
assert(resultWithoutOption)(equalTo(respArgs("key")))
} yield assert(result)(equalTo(RespCommand(Key("key"), Literal("PERSIST")))) &&
assert(resultWithoutOption)(equalTo(RespCommand(Key("key"))))
}
),
suite("YesNo")(
test("yes") {
for {
result <- ZIO.attempt(YesNoInput.encode(true))
} yield assert(result)(equalTo(respArgs("YES")))
} yield assert(result)(equalTo(RespCommand(Literal("YES"))))
},
test("no") {
for {
result <- ZIO.attempt(YesNoInput.encode(false))
} yield assert(result)(equalTo(respArgs("NO")))
} yield assert(result)(equalTo(RespCommand(Literal("NO"))))
}
)
)
private def respArgs(xs: String*): Chunk[RespValue] = Chunk.fromIterable(xs.map(RespValue.bulkString))
}
......@@ -44,6 +44,15 @@ trait KeysSpec extends BaseSpec {
e2 <- redis.exists("unknown")
} yield assert(e1)(equalTo(1L)) && assert(e2)(equalTo(0L))
},
test("check multiple existence") {
for {
redis <- ZIO.service[Redis]
key <- uuid
value <- uuid
_ <- redis.set(key, value)
e1 <- redis.exists(key, "unknown")
} yield assert(e1)(equalTo(1L))
} @@ clusterExecutorUnsupported,
test("delete existing key") {
for {
redis <- ZIO.service[Redis]
......@@ -53,6 +62,17 @@ trait KeysSpec extends BaseSpec {
deleted <- redis.del(key)
} yield assert(deleted)(equalTo(1L))
},
test("delete multiple existing key") {
for {
redis <- ZIO.service[Redis]
key1 <- uuid
key2 <- uuid
value <- uuid
_ <- redis.set(key1, value)
_ <- redis.set(key2, value)
deleted <- redis.del(key1, key2)
} yield assert(deleted)(equalTo(2L))
} @@ clusterExecutorUnsupported,
test("find all keys matching pattern") {
for {
redis <- ZIO.service[Redis]
......@@ -72,7 +92,7 @@ trait KeysSpec extends BaseSpec {
_ <- redis.set(key, value)
removed <- redis.unlink(key)
} yield assert(removed)(equalTo(1L))
},
} @@ clusterExecutorUnsupported,
test("touch two existing keys") {
for {
redis <- ZIO.service[Redis]
......@@ -96,7 +116,7 @@ trait KeysSpec extends BaseSpec {
(next, elements) = scan
} yield assert(next)(isGreaterThanEqualTo(0L)) && assert(elements)(isNonEmpty)
}
) @@ flaky,
) @@ flaky @@ clusterExecutorUnsupported,
test("fetch random key") {
for {
redis <- ZIO.service[Redis]
......@@ -106,7 +126,7 @@ trait KeysSpec extends BaseSpec {
allKeys <- redis.keys("*").returning[String]
randomKey <- redis.randomKey.returning[String]
} yield assert(allKeys)(contains(randomKey.get))
} @@ ignore,
} @@ ignore @@ clusterExecutorUnsupported,
test("dump followed by restore") {
for {
redis <- ZIO.service[Redis]
......
package zio.redis
import zio._
import zio.redis.Input.{BoolInput, ByteInput, LongInput, StringInput}
import zio.redis.Input.{BoolInput, LongInput, StringInput, ValueInput}
import zio.redis.Output._
import zio.redis.RedisError._
import zio.redis.ScriptingSpec._
......@@ -162,7 +162,7 @@ trait ScriptingSpec extends BaseSpec {
res <- redis.evalSha(lua, emptyInput, emptyInput).returning[String].either
} yield assert(res)(isLeft(isSubtype[NoScript](hasField("message", _.message, equalTo(error)))))
}
),
) @@ clusterExecutorUnsupported,
suite("scriptDebug")(
test("enable non-blocking asynchronous debugging") {
for {
......@@ -202,7 +202,7 @@ trait ScriptingSpec extends BaseSpec {
res <- redis.scriptExists(lua1, lua2)
} yield assertTrue(res == Chunk(false, false))
}
),
) @@ clusterExecutorUnsupported,
suite("scriptFlush")(
test("flush scripts in default mode") {
val lua1 = """return "1""""
......@@ -237,7 +237,7 @@ trait ScriptingSpec extends BaseSpec {
res <- redis.scriptExists(sha1, sha2)
} yield assertTrue(res == Chunk(false, false))
}
),
) @@ clusterExecutorUnsupported,
suite("scriptKill")(
test("return NOTBUSY when there is no scripts in execution") {
for {
......@@ -245,7 +245,7 @@ trait ScriptingSpec extends BaseSpec {
res <- redis.scriptKill.either
} yield assert(res)(isLeft(isSubtype[RedisError.NotBusy](anything)))
}
),
) @@ clusterExecutorUnsupported,
suite("scriptLoad")(
test("return OK") {
val lua = """return "1""""
......@@ -262,7 +262,7 @@ trait ScriptingSpec extends BaseSpec {
sha <- redis.scriptLoad(lua).either
} yield assert(sha)(isLeft(isSubtype[ProtocolError](hasField("message", _.message, equalTo(error)))))
}
)
) @@ clusterExecutorUnsupported
)
}
......@@ -301,7 +301,7 @@ object ScriptingSpec {
case other => throw ProtocolError(s"$other isn't a string type")
}
implicit val bytesEncoder: Input[Chunk[Byte]] = ByteInput
implicit val bytesEncoder: Input[Chunk[Byte]] = ValueInput
implicit val booleanInput: Input[Boolean] = BoolInput
implicit val stringInput: Input[String] = StringInput
implicit val longInput: Input[Long] = LongInput
......
......@@ -3,7 +3,7 @@ package zio.redis
import zio._
import zio.redis.RedisError._
import zio.test.Assertion._
import zio.test.TestAspect.ignore
import zio.test.TestAspect.{flaky, ignore}
import zio.test._
trait StreamsSpec extends BaseSpec {
......@@ -926,7 +926,7 @@ trait StreamsSpec extends BaseSpec {
assert(result.owner)(equalTo(consumer)) &&
assert(result.lastDelivered)(isGreaterThan(0.millis)) &&
assert(result.counter)(equalTo(1L))
},
} @@ flaky,
test("with multiple message, unlimited start, unlimited end and count with value 10") {
for {
redis <- ZIO.service[Redis]
......@@ -950,7 +950,7 @@ trait StreamsSpec extends BaseSpec {
assert(secondResult.owner)(equalTo(second)) &&
assert(secondResult.lastDelivered)(isGreaterThan(0.millis)) &&
assert(secondResult.counter)(equalTo(1L))
},
} @@ flaky,
test("with unlimited start, unlimited end, count with value 10, and the specified consumer") {
for {
redis <- ZIO.service[Redis]
......@@ -1078,7 +1078,7 @@ trait StreamsSpec extends BaseSpec {
)
)
)
},
} @@ clusterExecutorUnsupported,
test("with the positive count") {
for {
redis <- ZIO.service[Redis]
......@@ -1226,7 +1226,7 @@ trait StreamsSpec extends BaseSpec {
)
)
)
},
} @@ clusterExecutorUnsupported,
test("with positive count") {
for {
redis <- ZIO.service[Redis]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册