1 minute read

Categories:
Tags:

//TODO

The testing client for a performance test can be the same as one created for local unit tests.

Performance Testing Implementation

A sample implementation for performance testing would timestamp on Data element updates allowing clients to compare time lag between server updates and their notification of it.

Performance testing implementation and results are covered in Realtime Client Database Performance Testing.

class ClockExternalDataLayer private(clock: Clock, refreshSchedule: Schedule[Any, Any, Any])
  extends ExternalDataLayer(refreshSchedule) {

  override protected def externalData(
                                       chunk: NonEmptyChunk[Either[DataId, DataRecord]]
                                     ): UIO[Chunk[Data]] = {
    clock.instant.map {
      now =>
        val dataId = either.fold(identity, _.data.id)
        chunk.map(either => Data.of(dataId, now.toString))
    }
  }
}
case class GrpcClient(
                       userId: UserId,
                       requests: Queue[SyncRequest],
                       responses: Stream[Throwable, (UserId, SyncResponse)],
                       grpcLayer: ZLayer[Any, Throwable, SyncServiceClient],
                     ) {

  def update(request: UpdateRequest): IO[Throwable, UpdateResponse] = {
    SyncServiceClient.update(request).provideLayer(grpcLayer)
  }
}
object GrpcClient {
  def launch(
              userId: UserId,
              serverAddress: String,
              serverPort: Int,
            ): ZIO[Scope, Nothing, GrpcClient] = ZIO.scoped(Queue.unbounded[SyncRequest]).map {

    requests =>

      val grpcLayer: ZLayer[Any, Throwable, SyncServiceClient] = SyncServiceClient.live(
        ZManagedChannel(ManagedChannelBuilder.forAddress(serverAddress, serverPort).usePlaintext()),
        options = CallOptions.DEFAULT,
        metadata = SafeMetadata.make((AuthenticatedUser.MetadataUserIdKey, userId.toString)),
      )

      val responses = SyncServiceClient
        .bidirectionalStream(ZStream.fromQueue(requests))
        .provideLayer(grpcLayer)
        .map((userId, _))

      GrpcClient(userId, requests, responses, grpcLayer)
  }
}

Data ids: 1 - 600 are second markers. 601 - 1000 are random

Clients: Subscribe 1 - 600, subscribe i mod clientid


Sources

GitHub

Realtime Push Database

Realtime Database using ZIO Hub and Bi-Directional gRPC Streams.
Other Posts in this Series

Realtime Client Database: gRPC Bi-Directional Streams and ZIO Hub

6 minute read

, ,

Realtime push-based databases such as Google Firebase conveniently ensure clients are synchronized with the server. Data updates stream to clients immediately as they happen; and if a client disconnects, updates are immediately processed after reconnecting. gRPC server streaming and ZIO Hub can implement this functionality replicating an expensive paid Firebase service while allowing greater extensibility.

Realtime Client Database: External Datasource using ZIO ZLayer

2 minute read

, ,

Expanding on the realtime Firebase implementation in the previous article, this expands the functionality allowing the server to fetch data on-demand from an external datasource. Additionally, functionality to periodical refresh active data which is subscribed to by connected clients transforms this database into an efficient cache to evolving external data which can only be obtained by polling.

Categories:
Tags:
Updated: