Skip to content

Commit 8afb635

Browse files
authored
refactor: executeUpdate (#24)
* refactor: executeUpdate * refactor: fail_ci_if_error: false due to codecov/codecov-action#598 * export 'src/interface/transactionally_storage.dart'; * changelog
1 parent 4318a71 commit 8afb635

File tree

9 files changed

+88
-47
lines changed

9 files changed

+88
-47
lines changed

.github/workflows/dart.yml

+2
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,5 @@ jobs:
5858
run: dart pub global run coverage:format_coverage --lcov --in=coverage.json --out=lcov.info --report-on=lib
5959

6060
- uses: codecov/[email protected]
61+
with:
62+
fail_ci_if_error: false

.idea/vcs.xml

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
## 2.1.0-dev.0 - TODO
2+
3+
- Refactor `executeUpdate`:
4+
- Convert to named parameters.
5+
- Moved to `TransactionallyStorage`.
6+
- Update docs.
7+
- `Transformer` can return a `Future`.
8+
19
## 2.0.0 - Jun 1, 2022
210

311
- Update dependencies

lib/rx_storage.dart

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ library rx_storage;
66
export 'src/impl/real_storage.dart';
77
export 'src/interface/rx_storage.dart';
88
export 'src/interface/storage.dart';
9+
export 'src/interface/transactionally_storage.dart';
910
export 'src/logger/default_logger.dart';
1011
export 'src/logger/empty_logger.dart';
1112
export 'src/logger/event.dart';

lib/src/impl/real_storage.dart

+11-7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import '../async/async_memoizer.dart';
88
import '../async/async_queue.dart';
99
import '../interface/rx_storage.dart';
1010
import '../interface/storage.dart';
11+
import '../interface/transactionally_storage.dart';
1112
import '../logger/event.dart';
1213
import '../logger/logger.dart';
1314
import '../model/error.dart';
@@ -332,22 +333,25 @@ class RealRxStorage<Key extends Object, Options,
332333
@experimental
333334
@nonVirtual
334335
@override
335-
Future<void> executeUpdate<T extends Object>(
336-
Key key,
337-
Decoder<T?> decoder,
338-
Transformer<T?> transformer,
339-
Encoder<T?> encoder, [
336+
Future<void> executeUpdate<T extends Object>({
337+
required Key key,
338+
required Decoder<T?> decoder,
339+
required Transformer<T?> transformer,
340+
required Encoder<T?> encoder,
340341
Options? options,
341-
]) {
342+
}) {
342343
assert(_debugAssertNotDisposed());
343344

344345
return _enqueueWritingTask<void>(
345346
key,
346347
() async {
347348
// Read
348349
final value = await read<T>(key, decoder, options);
350+
349351
// Modify
350-
final transformed = transformer(value);
352+
final futureOr = transformer(value);
353+
final transformed = futureOr is Future<T?> ? await futureOr : futureOr;
354+
351355
// Write
352356
await _writeWithoutSynchronization(key, transformed, encoder, options);
353357
},

lib/src/interface/rx_storage.dart

+2-21
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
import 'dart:async';
22

3-
import 'package:meta/meta.dart';
4-
53
import '../impl/real_storage.dart';
64
import '../logger/logger.dart';
75
import 'storage.dart';
8-
9-
/// Transform a value to another value with same type.
10-
typedef Transformer<T> = T Function(T);
6+
import 'transactionally_storage.dart';
117

128
/// Get [Stream]s by key from persistent storage.
139
abstract class RxStorage<Key extends Object, Options>
14-
implements Storage<Key, Options> {
10+
implements TransactionallyStorage<Key, Options> {
1511
/// Constructs a [RxStorage] by wrapping a [Storage].
1612
factory RxStorage(
1713
FutureOr<Storage<Key, Options>> storageOrFuture, [
@@ -24,21 +20,6 @@ abstract class RxStorage<Key extends Object, Options>
2420
onDispose,
2521
);
2622

27-
/// `Read–modify–write`.
28-
///
29-
/// Read value by [key], then decode with [decoder],
30-
/// then transform by [transformer],
31-
/// then encode with [encoder]
32-
/// and finally save decoded value to persistent storage.
33-
@experimental
34-
Future<void> executeUpdate<T extends Object>(
35-
Key key,
36-
Decoder<T?> decoder,
37-
Transformer<T?> transformer,
38-
Encoder<T?> encoder, [
39-
Options? options,
40-
]);
41-
4223
/// Return [Stream] that will emit value read from persistent storage.
4324
/// It will automatic emit value when value associated with key was changed.
4425
Stream<T?> observe<T extends Object>(Key key, Decoder<T?> decoder,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import 'package:meta/meta.dart';
2+
import 'dart:async';
3+
4+
import 'storage.dart';
5+
6+
/// Transform a value to another value of the same type.
7+
typedef Transformer<T> = FutureOr<T> Function(T);
8+
9+
/// A persistent store for simple data.
10+
/// Data is persisted to disk asynchronously and transactionally.
11+
abstract class TransactionallyStorage<Key extends Object, Options>
12+
implements Storage<Key, Options> {
13+
/// `Read–modify–write`.
14+
///
15+
/// Updates the data transactionally in an atomic read-modify-write operation.
16+
/// All operations are serialized, and the [transformer] can perform asynchronous computations
17+
/// such as RPCs, database queries, API calls, etc.
18+
///
19+
/// The future completes when the data has been persisted durably to disk.
20+
/// If the transform or write to disk fails, the transaction is aborted and the error is rethrown.
21+
///
22+
/// When calling this, logic will be executed in the following order:
23+
/// - Read raw value by [key], then decode it with [decoder].
24+
/// - Transform the decoded value with [transformer].
25+
/// - Encode the transformed value with [encoder].
26+
/// - Finally, save encoded value to persistent storage.
27+
@experimental
28+
Future<void> executeUpdate<T extends Object>({
29+
required Key key,
30+
required Decoder<T?> decoder,
31+
required Transformer<T?> transformer,
32+
required Encoder<T?> encoder,
33+
Options? options,
34+
});
35+
}

pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: rx_storage
22
description: Reactive storage for Dart/Flutter. RxDart Storage for Dart/Flutter.
3-
version: 2.0.0
3+
version: 2.1.0-dev.0
44
homepage: https://github.com/Flutter-Dart-Open-Source/rx_storage.git
55
repository: https://github.com/Flutter-Dart-Open-Source/rx_storage.git
66
issue_tracker: https://github.com/Flutter-Dart-Open-Source/rx_storage/issues

test/storage/streams_test.dart

+22-18
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ void main() {
3333
);
3434
});
3535

36-
tearDown(() {
36+
tearDown(() async {
3737
try {
38-
rxStorage.dispose();
38+
await rxStorage.dispose();
3939
} catch (_) {}
4040
});
4141

@@ -379,10 +379,10 @@ void main() {
379379
);
380380

381381
await rxStorage.executeUpdate<String>(
382-
'String',
383-
(s) => s as String?, // read
384-
(s) => 'Transformed $s', // modify,
385-
(s) => s, // write
382+
key: 'String',
383+
decoder: (s) => s as String?, // read
384+
transformer: (s) => 'Transformed $s', // modify,
385+
encoder: (s) => s, // write
386386
);
387387

388388
expect(
@@ -403,11 +403,13 @@ void main() {
403403
);
404404

405405
await rxStorage.executeUpdate<User>(
406-
'User',
407-
jsonStringToUser, // read
408-
(user) => user?.withName('Transformed ${user.name}'),
406+
key: 'User',
407+
// read
408+
decoder: jsonStringToUser,
409409
// modify
410-
userToJsonString, // write
410+
transformer: (user) => user?.withName('Transformed ${user.name}'),
411+
// write
412+
encoder: userToJsonString,
411413
);
412414

413415
expect(
@@ -422,20 +424,22 @@ void main() {
422424

423425
expect(
424426
rxStorage.executeUpdate<String>(
425-
'String',
426-
(s) => s as String?, // read
427-
(s) => 'Transformed $s', // modify,
428-
(s) => s, // write
427+
key: 'String',
428+
decoder: (s) => s as String?, // read
429+
transformer: (s) => 'Transformed $s', // modify,
430+
encoder: (s) => s, // write
429431
),
430432
throwsException,
431433
);
432434
expect(
433435
rxStorage.executeUpdate<User>(
434-
'User',
435-
jsonStringToUser, // read
436-
(user) => user?.withName('Transformed ${user.name}'),
436+
key: 'User',
437+
// read
438+
decoder: jsonStringToUser,
437439
// modify
438-
userToJsonString, // write
440+
transformer: (user) => user?.withName('Transformed ${user.name}'),
441+
// write
442+
encoder: userToJsonString,
439443
),
440444
throwsException,
441445
);

0 commit comments

Comments
 (0)