Realtime Client Database: Performance Testing in the Cloud
//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
Realtime Push Database
Realtime Database using ZIO Hub and Bi-Directional gRPC Streams.- Main.scala
- ZSyncServiceImpl.scala
- ZSyncServiceImplSpec.scala
- ExternalDataLayer.scala
- ClockExternalDataLayer.scala
- Effects.scala
- sync_service.proto
Realtime Client Database: gRPC Bi-Directional Streams and ZIO Hub
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
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.