Skip to content

Commit

Permalink
refactor: executeUpdate (#24)
Browse files Browse the repository at this point in the history
* refactor: executeUpdate

* refactor: fail_ci_if_error: false due to codecov/codecov-action#598

* export 'src/interface/transactionally_storage.dart';

* changelog
  • Loading branch information
hoc081098 authored Nov 2, 2022
1 parent 4318a71 commit 8afb635
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 47 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/dart.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,5 @@ jobs:
run: dart pub global run coverage:format_coverage --lcov --in=coverage.json --out=lcov.info --report-on=lib

- uses: codecov/[email protected]
with:
fail_ci_if_error: false
6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 2.1.0-dev.0 - TODO

- Refactor `executeUpdate`:
- Convert to named parameters.
- Moved to `TransactionallyStorage`.
- Update docs.
- `Transformer` can return a `Future`.

## 2.0.0 - Jun 1, 2022

- Update dependencies
Expand Down
1 change: 1 addition & 0 deletions lib/rx_storage.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ library rx_storage;
export 'src/impl/real_storage.dart';
export 'src/interface/rx_storage.dart';
export 'src/interface/storage.dart';
export 'src/interface/transactionally_storage.dart';
export 'src/logger/default_logger.dart';
export 'src/logger/empty_logger.dart';
export 'src/logger/event.dart';
Expand Down
18 changes: 11 additions & 7 deletions lib/src/impl/real_storage.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import '../async/async_memoizer.dart';
import '../async/async_queue.dart';
import '../interface/rx_storage.dart';
import '../interface/storage.dart';
import '../interface/transactionally_storage.dart';
import '../logger/event.dart';
import '../logger/logger.dart';
import '../model/error.dart';
Expand Down Expand Up @@ -332,22 +333,25 @@ class RealRxStorage<Key extends Object, Options,
@experimental
@nonVirtual
@override
Future<void> executeUpdate<T extends Object>(
Key key,
Decoder<T?> decoder,
Transformer<T?> transformer,
Encoder<T?> encoder, [
Future<void> executeUpdate<T extends Object>({
required Key key,
required Decoder<T?> decoder,
required Transformer<T?> transformer,
required Encoder<T?> encoder,
Options? options,
]) {
}) {
assert(_debugAssertNotDisposed());

return _enqueueWritingTask<void>(
key,
() async {
// Read
final value = await read<T>(key, decoder, options);

// Modify
final transformed = transformer(value);
final futureOr = transformer(value);
final transformed = futureOr is Future<T?> ? await futureOr : futureOr;

// Write
await _writeWithoutSynchronization(key, transformed, encoder, options);
},
Expand Down
23 changes: 2 additions & 21 deletions lib/src/interface/rx_storage.dart
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
import 'dart:async';

import 'package:meta/meta.dart';

import '../impl/real_storage.dart';
import '../logger/logger.dart';
import 'storage.dart';

/// Transform a value to another value with same type.
typedef Transformer<T> = T Function(T);
import 'transactionally_storage.dart';

/// Get [Stream]s by key from persistent storage.
abstract class RxStorage<Key extends Object, Options>
implements Storage<Key, Options> {
implements TransactionallyStorage<Key, Options> {
/// Constructs a [RxStorage] by wrapping a [Storage].
factory RxStorage(
FutureOr<Storage<Key, Options>> storageOrFuture, [
Expand All @@ -24,21 +20,6 @@ abstract class RxStorage<Key extends Object, Options>
onDispose,
);

/// `Read–modify–write`.
///
/// Read value by [key], then decode with [decoder],
/// then transform by [transformer],
/// then encode with [encoder]
/// and finally save decoded value to persistent storage.
@experimental
Future<void> executeUpdate<T extends Object>(
Key key,
Decoder<T?> decoder,
Transformer<T?> transformer,
Encoder<T?> encoder, [
Options? options,
]);

/// Return [Stream] that will emit value read from persistent storage.
/// It will automatic emit value when value associated with key was changed.
Stream<T?> observe<T extends Object>(Key key, Decoder<T?> decoder,
Expand Down
35 changes: 35 additions & 0 deletions lib/src/interface/transactionally_storage.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import 'package:meta/meta.dart';
import 'dart:async';

import 'storage.dart';

/// Transform a value to another value of the same type.
typedef Transformer<T> = FutureOr<T> Function(T);

/// A persistent store for simple data.
/// Data is persisted to disk asynchronously and transactionally.
abstract class TransactionallyStorage<Key extends Object, Options>
implements Storage<Key, Options> {
/// `Read–modify–write`.
///
/// Updates the data transactionally in an atomic read-modify-write operation.
/// All operations are serialized, and the [transformer] can perform asynchronous computations
/// such as RPCs, database queries, API calls, etc.
///
/// The future completes when the data has been persisted durably to disk.
/// If the transform or write to disk fails, the transaction is aborted and the error is rethrown.
///
/// When calling this, logic will be executed in the following order:
/// - Read raw value by [key], then decode it with [decoder].
/// - Transform the decoded value with [transformer].
/// - Encode the transformed value with [encoder].
/// - Finally, save encoded value to persistent storage.
@experimental
Future<void> executeUpdate<T extends Object>({
required Key key,
required Decoder<T?> decoder,
required Transformer<T?> transformer,
required Encoder<T?> encoder,
Options? options,
});
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: rx_storage
description: Reactive storage for Dart/Flutter. RxDart Storage for Dart/Flutter.
version: 2.0.0
version: 2.1.0-dev.0
homepage: https://github.com/Flutter-Dart-Open-Source/rx_storage.git
repository: https://github.com/Flutter-Dart-Open-Source/rx_storage.git
issue_tracker: https://github.com/Flutter-Dart-Open-Source/rx_storage/issues
Expand Down
40 changes: 22 additions & 18 deletions test/storage/streams_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ void main() {
);
});

tearDown(() {
tearDown(() async {
try {
rxStorage.dispose();
await rxStorage.dispose();
} catch (_) {}
});

Expand Down Expand Up @@ -379,10 +379,10 @@ void main() {
);

await rxStorage.executeUpdate<String>(
'String',
(s) => s as String?, // read
(s) => 'Transformed $s', // modify,
(s) => s, // write
key: 'String',
decoder: (s) => s as String?, // read
transformer: (s) => 'Transformed $s', // modify,
encoder: (s) => s, // write
);

expect(
Expand All @@ -403,11 +403,13 @@ void main() {
);

await rxStorage.executeUpdate<User>(
'User',
jsonStringToUser, // read
(user) => user?.withName('Transformed ${user.name}'),
key: 'User',
// read
decoder: jsonStringToUser,
// modify
userToJsonString, // write
transformer: (user) => user?.withName('Transformed ${user.name}'),
// write
encoder: userToJsonString,
);

expect(
Expand All @@ -422,20 +424,22 @@ void main() {

expect(
rxStorage.executeUpdate<String>(
'String',
(s) => s as String?, // read
(s) => 'Transformed $s', // modify,
(s) => s, // write
key: 'String',
decoder: (s) => s as String?, // read
transformer: (s) => 'Transformed $s', // modify,
encoder: (s) => s, // write
),
throwsException,
);
expect(
rxStorage.executeUpdate<User>(
'User',
jsonStringToUser, // read
(user) => user?.withName('Transformed ${user.name}'),
key: 'User',
// read
decoder: jsonStringToUser,
// modify
userToJsonString, // write
transformer: (user) => user?.withName('Transformed ${user.name}'),
// write
encoder: userToJsonString,
),
throwsException,
);
Expand Down

0 comments on commit 8afb635

Please sign in to comment.