Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: use type-specific methods in public clients, Value in internal clients #90

Merged
merged 10 commits into from
Jan 12, 2024
4 changes: 2 additions & 2 deletions example/flutter_chat_app/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ class _MyHomePageState extends State<MyHomePage> {
}

Future<void> publishMessage() async {
final result = await _topicClient.publish(
"cache", "topic", StringValue(_textInputController.text));
final result =
await _topicClient.publish("cache", "topic", _textInputController.text);
switch (result) {
case TopicPublishSuccess():
print("Successful publish");
Expand Down
4 changes: 2 additions & 2 deletions example/quickstart/quickstart.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ Future<void> main() async {
Duration(seconds: 30));

final cacheName = "cache";
final key = StringValue("key");
final value = StringValue("value");
final key = "key";
final value = "value";

final setResp = await cacheClient.set(cacheName, key, value);
switch (setResp) {
Expand Down
3 changes: 1 addition & 2 deletions example/topics/advanced.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ void main() async {
Timer(const Duration(seconds: 2), () async {
// publish 10 messages spaced 1 second apart
for (final i in Iterable.generate(10)) {
var result =
await topicClient.publish("cache", "topic", StringValue("hi $i"));
var result = await topicClient.publish("cache", "topic", "hi $i");
switch (result) {
case TopicPublishSuccess():
print("Successful publish!");
Expand Down
3 changes: 1 addition & 2 deletions example/topics/basic_publisher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ void main() async {

// publish 10 messages spaced 1 second apart
for (final i in Iterable.generate(10)) {
var result =
await topicClient.publish("cache", "topic", StringValue("hi $i"));
var result = await topicClient.publish("cache", "topic", "hi $i");
switch (result) {
case TopicPublishSuccess():
print("Successful publish!");
Expand Down
89 changes: 54 additions & 35 deletions lib/src/cache_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:momento/src/internal/data_client.dart';
import 'package:momento/src/internal/utils/validators.dart';

import 'config/logger.dart';
import 'internal/utils/utils.dart';

abstract class ICacheClient {
// Control plane RPCs
Expand All @@ -16,20 +17,20 @@ abstract class ICacheClient {
Future<ListCachesResponse> listCaches();

// Unary RPCs
Future<GetResponse> get(String cacheName, Value key);
Future<GetResponse> get(String cacheName, dynamic key);

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

Future<DeleteResponse> delete(String cacheName, Value key);
Future<DeleteResponse> delete(String cacheName, dynamic key);

// List Collection RPCs
Future<ListConcatenateBackResponse> listConcatenateBack(
String cacheName, String listName, List<Value> values,
String cacheName, String listName, List<dynamic> values,
{CollectionTtl? ttl, int? truncateFrontToSize});

Future<ListConcatenateFrontResponse> listConcatenateFront(
String cacheName, String listName, List<Value> values,
String cacheName, String listName, List<dynamic> values,
{CollectionTtl? ttl, int? truncateBackToSize});

Future<ListFetchResponse> listFetch(String cacheName, String listName,
Expand All @@ -39,15 +40,15 @@ abstract class ICacheClient {
Future<ListPopFrontResponse> listPopFront(String cacheName, String listName);

Future<ListPushBackResponse> listPushBack(
String cacheName, String listName, Value value,
String cacheName, String listName, dynamic value,
{CollectionTtl? ttl, int? truncateFrontToSize});

Future<ListPushFrontResponse> listPushFront(
String cacheName, String listName, Value value,
String cacheName, String listName, dynamic value,
{CollectionTtl? ttl, int? truncateBackToSize});

Future<ListRemoveValueResponse> listRemoveValue(
String cacheName, String listName, Value value);
String cacheName, String listName, dynamic value);

Future<ListRetainResponse> listRetain(String cacheName, String listName,
{int? startIndex, int? endIndex, CollectionTtl? ttl});
Expand Down Expand Up @@ -159,9 +160,11 @@ class CacheClient implements ICacheClient {
/// }
/// ```
@override
Future<GetResponse> get(String cacheName, Value key) {
Future<GetResponse> get(String cacheName, dynamic key) {
Value validatedKey;
try {
validateCacheName(cacheName);
validatedKey = getStringOrBinaryFromDynamic(key, "key");
} catch (e) {
if (e is SdkException) {
return Future.value(GetError(e));
Expand All @@ -170,7 +173,7 @@ class CacheClient implements ICacheClient {
GetError(UnknownException("Unexpected error: $e", null, null)));
}
}
return _dataClient.get(cacheName, key);
return _dataClient.get(cacheName, validatedKey);
}

/// Associates the given key with the given value.
Expand All @@ -186,10 +189,14 @@ class CacheClient implements ICacheClient {
/// }
/// ```
@override
Future<SetResponse> set(String cacheName, Value key, Value value,
Future<SetResponse> set(String cacheName, dynamic key, dynamic value,
{Duration? ttl}) {
Value validatedKey;
Value validatedValue;
try {
validateCacheName(cacheName);
validatedKey = getStringOrBinaryFromDynamic(key, "key");
validatedValue = getStringOrBinaryFromDynamic(value, "value");
} catch (e) {
if (e is SdkException) {
return Future.value(SetError(e));
Expand All @@ -198,7 +205,7 @@ class CacheClient implements ICacheClient {
SetError(UnknownException("Unexpected error: $e", null, null)));
}
}
return _dataClient.set(cacheName, key, value, ttl: ttl);
return _dataClient.set(cacheName, validatedKey, validatedValue, ttl: ttl);
}

/// Removes the given key from the cache.
Expand All @@ -214,9 +221,11 @@ class CacheClient implements ICacheClient {
/// }
/// ```
@override
Future<DeleteResponse> delete(String cacheName, Value key) {
Future<DeleteResponse> delete(String cacheName, dynamic key) {
Value validatedKey;
try {
validateCacheName(cacheName);
validatedKey = getStringOrBinaryFromDynamic(key, "key");
} catch (e) {
if (e is SdkException) {
return Future.value(DeleteError(e));
Expand All @@ -225,22 +234,22 @@ class CacheClient implements ICacheClient {
DeleteError(UnknownException("Unexpected error: $e", null, null)));
}
}
return _dataClient.delete(cacheName, key);
return _dataClient.delete(cacheName, validatedKey);
}

/// Close the client and free up all associated resources.
///
/// NOTE: the client object will not be usable after calling this method.
@override
Future<ListConcatenateBackResponse> listConcatenateBack(
String cacheName, String listName, List<Value> values,
String cacheName, String listName, List<dynamic> values,
{CollectionTtl? ttl, int? truncateFrontToSize}) {
List<Value> validatedList;
try {
validateCacheName(cacheName);
validateListName(listName);
validateList(values);
return _dataClient.listConcatenateBack(cacheName, listName, values,
ttl: ttl, truncateFrontToSize: truncateFrontToSize);
validatedList = getListOfStringOrBinaryFromDynamic(values, "list");
validateList(validatedList);
} catch (e) {
if (e is SdkException) {
return Future.value(ListConcatenateBackError(e));
Expand All @@ -249,18 +258,20 @@ class CacheClient implements ICacheClient {
UnknownException("Unexpected error: $e", null, null)));
}
}
return _dataClient.listConcatenateBack(cacheName, listName, validatedList,
ttl: ttl, truncateFrontToSize: truncateFrontToSize);
}

@override
Future<ListConcatenateFrontResponse> listConcatenateFront(
String cacheName, String listName, List<Value> values,
String cacheName, String listName, List<dynamic> values,
{CollectionTtl? ttl, int? truncateBackToSize}) {
List<Value> validatedList;
try {
validateCacheName(cacheName);
validateListName(listName);
validateList(values);
return _dataClient.listConcatenateFront(cacheName, listName, values,
ttl: ttl, truncateBackToSize: truncateBackToSize);
validatedList = getListOfStringOrBinaryFromDynamic(values, "list");
validateList(validatedList);
} catch (e) {
if (e is SdkException) {
return Future.value(ListConcatenateFrontError(e));
Expand All @@ -269,6 +280,8 @@ class CacheClient implements ICacheClient {
UnknownException("Unexpected error: $e", null, null)));
}
}
return _dataClient.listConcatenateFront(cacheName, listName, validatedList,
ttl: ttl, truncateBackToSize: truncateBackToSize);
}

@override
Expand All @@ -277,8 +290,6 @@ class CacheClient implements ICacheClient {
try {
validateCacheName(cacheName);
validateListName(listName);
return _dataClient.listFetch(cacheName, listName,
startIndex: startIndex, endIndex: endIndex);
} catch (e) {
if (e is SdkException) {
return Future.value(ListFetchError(e));
Expand All @@ -287,14 +298,15 @@ class CacheClient implements ICacheClient {
UnknownException("Unexpected error: $e", null, null)));
}
}
return _dataClient.listFetch(cacheName, listName,
startIndex: startIndex, endIndex: endIndex);
}

@override
Future<ListLengthResponse> listLength(String cacheName, String listName) {
try {
validateCacheName(cacheName);
validateListName(listName);
return _dataClient.listLength(cacheName, listName);
} catch (e) {
if (e is SdkException) {
return Future.value(ListLengthError(e));
Expand All @@ -303,14 +315,14 @@ class CacheClient implements ICacheClient {
UnknownException("Unexpected error: $e", null, null)));
}
}
return _dataClient.listLength(cacheName, listName);
}

@override
Future<ListPopBackResponse> listPopBack(String cacheName, String listName) {
try {
validateCacheName(cacheName);
validateListName(listName);
return _dataClient.listPopBack(cacheName, listName);
} catch (e) {
if (e is SdkException) {
return Future.value(ListPopBackError(e));
Expand All @@ -319,14 +331,14 @@ class CacheClient implements ICacheClient {
UnknownException("Unexpected error: $e", null, null)));
}
}
return _dataClient.listPopBack(cacheName, listName);
}

@override
Future<ListPopFrontResponse> listPopFront(String cacheName, String listName) {
try {
validateCacheName(cacheName);
validateListName(listName);
return _dataClient.listPopFront(cacheName, listName);
} catch (e) {
if (e is SdkException) {
return Future.value(ListPopFrontError(e));
Expand All @@ -335,17 +347,18 @@ class CacheClient implements ICacheClient {
UnknownException("Unexpected error: $e", null, null)));
}
}
return _dataClient.listPopFront(cacheName, listName);
}

@override
Future<ListPushBackResponse> listPushBack(
String cacheName, String listName, Value value,
String cacheName, String listName, dynamic value,
{CollectionTtl? ttl, int? truncateFrontToSize}) {
Value validatedValue;
try {
validateCacheName(cacheName);
validateListName(listName);
return _dataClient.listPushBack(cacheName, listName, value,
ttl: ttl, truncateFrontToSize: truncateFrontToSize);
validatedValue = getStringOrBinaryFromDynamic(value, "value");
} catch (e) {
if (e is SdkException) {
return Future.value(ListPushBackError(e));
Expand All @@ -354,17 +367,19 @@ class CacheClient implements ICacheClient {
UnknownException("Unexpected error: $e", null, null)));
}
}
return _dataClient.listPushBack(cacheName, listName, validatedValue,
ttl: ttl, truncateFrontToSize: truncateFrontToSize);
}

@override
Future<ListPushFrontResponse> listPushFront(
String cacheName, String listName, Value value,
String cacheName, String listName, dynamic value,
{CollectionTtl? ttl, int? truncateBackToSize}) {
Value validatedValue;
try {
validateCacheName(cacheName);
validateListName(listName);
return _dataClient.listPushFront(cacheName, listName, value,
ttl: ttl, truncateBackToSize: truncateBackToSize);
validatedValue = getStringOrBinaryFromDynamic(value, "value");
} catch (e) {
if (e is SdkException) {
return Future.value(ListPushFrontError(e));
Expand All @@ -373,15 +388,18 @@ class CacheClient implements ICacheClient {
UnknownException("Unexpected error: $e", null, null)));
}
}
return _dataClient.listPushFront(cacheName, listName, validatedValue,
ttl: ttl, truncateBackToSize: truncateBackToSize);
}

@override
Future<ListRemoveValueResponse> listRemoveValue(
String cacheName, String listName, Value value) {
String cacheName, String listName, dynamic value) {
Value validatedValue;
try {
validateCacheName(cacheName);
validateListName(listName);
return _dataClient.listRemoveValue(cacheName, listName, value);
validatedValue = getStringOrBinaryFromDynamic(value, "value");
} catch (e) {
if (e is SdkException) {
return Future.value(ListRemoveValueError(e));
Expand All @@ -390,6 +408,7 @@ class CacheClient implements ICacheClient {
UnknownException("Unexpected error: $e", null, null)));
}
}
return _dataClient.listRemoveValue(cacheName, listName, validatedValue);
}

@override
Expand Down
24 changes: 24 additions & 0 deletions lib/src/internal/utils/utils.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import 'package:momento/momento.dart';
import 'package:momento/src/errors/errors.dart';

Value getStringOrBinaryFromDynamic(dynamic value, String parameterName) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a really cool thing to try!

I'm guessing the editor isn't able to give any type hints for this at all though? and it would be a runtime error if you just tried to pass in like, some random object type as the argument to one of these dynamic args? If so, lemme noodle on that.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If type hints are a good trade for an uglier API, we could add the type to the function name like we do with some of the collection methods in Java: dictionarySetFieldsStringBytes.

if (value is String) {
return StringValue(value);
} else if (value is List<int>) {
return BinaryValue(value);
} else if (value is Value) {
return value;
} else {
throw InvalidArgumentException(
"$parameterName must be a String or List<int>", null, null);
}
}

List<Value> getListOfStringOrBinaryFromDynamic(
List<dynamic> values, String parameterName) {
final list = <Value>[];
for (final value in values) {
list.add(getStringOrBinaryFromDynamic(value, parameterName));
}
return list;
}
Loading