All Downloads are FREE. Search and download functionalities are using the official Maven repository.

zio.redis.internal.RedisSubscriptionCommand.scala Maven / Gradle / Ivy

The newest version!
/*
 * 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.internal

import zio.redis.Input._
import zio.redis.Output.ArbitraryOutput
import zio.redis._
import zio.redis.api.Subscription
import zio.redis.api.Subscription.PubSubCallback
import zio.redis.internal.PubSub.PushMessage._
import zio.schema.codec.BinaryCodec
import zio.stream._
import zio.{Chunk, IO, ZIO}

private[redis] final case class RedisSubscriptionCommand(executor: SubscriptionExecutor) {
  def subscribe[A: BinaryCodec](
    channels: Chunk[String],
    onSubscribe: PubSubCallback,
    onUnsubscribe: PubSubCallback
  )(implicit codec: BinaryCodec[String]): Stream[RedisError, (String, A)] =
    executeCommand[A](makeCommand(Subscription.Subscribe, channels), onSubscribe, onUnsubscribe)

  def pSubscribe[A: BinaryCodec](
    patterns: Chunk[String],
    onSubscribe: PubSubCallback,
    onUnsubscribe: PubSubCallback
  )(implicit stringCodec: BinaryCodec[String]): Stream[RedisError, (String, A)] =
    executeCommand[A](makeCommand(Subscription.PSubscribe, patterns), onSubscribe, onUnsubscribe)

  def unsubscribe(channels: Chunk[String])(implicit codec: BinaryCodec[String]): IO[RedisError, Unit] =
    executor.execute(makeCommand(Subscription.Unsubscribe, channels)).runDrain

  def pUnsubscribe(patterns: Chunk[String])(implicit codec: BinaryCodec[String]): IO[RedisError, Unit] =
    executor.execute(makeCommand(Subscription.PUnsubscribe, patterns)).runDrain

  private def makeCommand(commandName: String, keys: Chunk[String])(implicit codec: BinaryCodec[String]) =
    CommandNameInput.encode(commandName) ++
      Varargs(ArbitraryKeyInput[String]()).encode(keys)

  private def executeCommand[A: BinaryCodec](
    command: RespCommand,
    onSubscribe: PubSubCallback,
    onUnsubscribe: PubSubCallback
  ): Stream[RedisError, (String, A)] =
    executor
      .execute(command)
      .mapZIO {
        case Subscribed(key, numOfSubs)   =>
          onSubscribe(key.value, numOfSubs).as(None)
        case Unsubscribed(key, numOfSubs) =>
          onUnsubscribe(key.value, numOfSubs).as(None)
        case Message(_, channel, message) =>
          ZIO
            .attempt(ArbitraryOutput[A]().unsafeDecode(message))
            .map(msg => Some((channel, msg)))
      }
      .collectSome
      .refineToOrDie[RedisError]
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy