Skip to content

Commit

Permalink
feat: add unary data client with get/set support (#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
bruuuuuuuce committed Dec 21, 2023
1 parent 6088ed8 commit a632ba9
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 1 deletion.
1 change: 1 addition & 0 deletions lib/client_sdk_dart.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
library;

export 'src/topic_client.dart';
export 'src/cache_client.dart';
export 'src/auth/credential_provider.dart';
export 'src/config/topic_configurations.dart';
export 'src/messages/values.dart';
Expand Down
40 changes: 40 additions & 0 deletions lib/src/cache_client.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import 'package:client_sdk_dart/src/config/cache_configuration.dart';
import 'package:client_sdk_dart/src/internal/data_client.dart';
import 'package:client_sdk_dart/src/messages/responses/cache/data/scalar/get_response.dart';
import 'package:client_sdk_dart/src/messages/responses/cache/data/scalar/set_response.dart';
import 'package:logging/logging.dart';

import 'auth/credential_provider.dart';
import 'config/logger.dart';
import 'messages/values.dart';

abstract class ICacheClient {
Future<GetResponse> get(String cacheName, Value value);

Future<SetResponse> set(String cacheName, Value key, Value value,
{Duration? ttl});
}

class CacheClient implements ICacheClient {
final DataClient _dataClient;
final Logger _logger = Logger('MomentoCacheClient');

CacheClient(CredentialProvider credentialProvider,
CacheConfiguration configuration, Duration defaultTtl)
: _dataClient =
DataClient(credentialProvider, configuration, defaultTtl) {
_logger.level = determineLoggerLevel(configuration.logLevel);
_logger.finest("initializing cache client");
}

@override
Future<GetResponse> get(String cacheName, Value value) {
return _dataClient.get(cacheName, value);
}

@override
Future<SetResponse> set(String cacheName, Value key, Value value,
{Duration? ttl}) {
return _dataClient.set(cacheName, key, value, ttl: ttl);
}
}
88 changes: 88 additions & 0 deletions lib/src/internal/data_client.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import 'package:client_sdk_dart/generated/cacheclient.pbgrpc.dart';
import 'package:client_sdk_dart/src/config/cache_configuration.dart';
import 'package:client_sdk_dart/src/errors/errors.dart';
import 'package:client_sdk_dart/src/messages/responses/cache/data/scalar/get_response.dart';
import 'package:client_sdk_dart/src/messages/responses/cache/data/scalar/set_response.dart';
import 'package:fixnum/fixnum.dart';
import 'package:grpc/grpc.dart';

import '../auth/credential_provider.dart';
import '../messages/values.dart';

abstract class AbstractDataClient {
Future<GetResponse> get(String cacheName, Value key);

Future<SetResponse> set(String cacheName, Value key, Value value,
{Duration? ttl});
}

class DataClient implements AbstractDataClient {
late ClientChannel _channel;
late ScsClient _client;
late CacheConfiguration _configuration;
late Duration _defaultTtl;

DataClient(CredentialProvider credentialProvider,
CacheConfiguration configuration, Duration defaultTtl) {
_channel = ClientChannel(credentialProvider.cacheEndpoint);
_client = ScsClient(_channel,
options: CallOptions(metadata: {
'authorization': credentialProvider.apiKey,
'agent': 'dart:0.1.0',
}, timeout: _configuration.transportStrategy.grpcConfig.deadline));
_configuration = configuration;
_defaultTtl = defaultTtl;
}

@override
Future<GetResponse> get(String cacheName, Value key) async {
var request = GetRequest_();
request.cacheKey = key.toBinary();
try {
var resp = await _client.get(request,
options: CallOptions(metadata: {
'cacheName': cacheName,
}));

switch (resp.result) {
case ECacheResult.Miss:
return GetMiss();
case ECacheResult.Hit:
return GetHit(resp.cacheBody);
default:
return GetError(UnknownException(
"unknown cache get error ${resp.result}", null, null));
}
} catch (e) {
if (e is SdkException) {
return GetError(e);
} else {
return GetError(UnknownException("Unexpected error: $e", null, null));
}
}
}

@override
Future<SetResponse> set(String cacheName, Value key, Value value,
{Duration? ttl}) async {
var request = SetRequest_();
request.cacheKey = key.toBinary();
request.cacheBody = value.toBinary();
request.ttlMilliseconds = (ttl != null
? ttl.inMilliseconds
: _defaultTtl.inMilliseconds) as Int64;
try {
await _client.set(request,
options: CallOptions(metadata: {
'cacheName': cacheName,
}));
return SetSuccess();
} catch (e) {
if (e is SdkException) {
return SetError(e);
} else {
return SetError(UnknownException("Unexpected error: $e", null, null));
}
}
}
}
20 changes: 20 additions & 0 deletions lib/src/messages/responses/cache/data/scalar/get_response.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'dart:convert';

import 'package:client_sdk_dart/src/messages/responses/responses_base.dart';

sealed class GetResponse {}

class GetMiss implements GetResponse {}

class GetError extends ErrorResponseBase implements GetResponse {
GetError(super.exception);
}

class GetHit implements GetResponse {
GetHit(this._value);

final List<int> _value;

String get value => utf8.decode(_value);
List<int> get binaryValue => _value;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import 'package:client_sdk_dart/src/messages/responses/responses_base.dart';

sealed class SetResponse {}

class SetSuccess implements SetResponse {}

class SetError extends ErrorResponseBase implements SetResponse {
SetError(super.exception);
}
27 changes: 26 additions & 1 deletion lib/src/messages/values.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,38 @@
sealed class Value {}
import 'dart:convert';

sealed class Value {
List<int> toBinary();
String toUtf8();
}

class StringValue implements Value {
final String _value;
StringValue(String v) : _value = v;
String get value => _value;

@override
toBinary() {
return utf8.encode(_value);
}

@override
toUtf8() {
return _value;
}
}

class BinaryValue implements Value {
final List<int> _value;
BinaryValue(List<int> v) : _value = v;
List<int> get value => _value;

@override
List<int> toBinary() {
return _value;
}

@override
String toUtf8() {
return utf8.decode(_value);
}
}
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ environment:

# Add regular dependencies here.
dependencies:
fixnum: ^1.1.0
grpc: ^3.2.4
jwt_decoder: ^2.0.1
logging: ^1.2.0
Expand Down

0 comments on commit a632ba9

Please sign in to comment.