Skip to content

Commit 7770f63

Browse files
committed
fromEncodable function is now configurable only at vault or cache level. Removed store wide fromEncodable to support multi-type stores
1 parent e9ed1eb commit 7770f63

File tree

75 files changed

+587
-700
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+587
-700
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,12 @@ void main() async {
184184
final path = Directory.systemTemp.path;
185185
186186
// Creates a store
187-
final store = await newFileLocalCacheStore(
188-
path: path, fromEncodable: (json) => Task.fromJson(json));
187+
final store = await newFileLocalCacheStore(path: path);
189188
190189
// Creates a cache with a capacity of 10 from the previously created store
191190
final cache = await store.cache<Task>(
192191
name: 'cache1',
192+
fromEncodable: (json) => Task.fromJson(json),
193193
maxEntries: 10,
194194
eventListenerMode: EventListenerMode.synchronous)
195195
..on<CacheEntryCreatedEvent<Task>>().listen(

packages/stash/lib/src/api/cache/cache_entry.dart

+3-6
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ class CacheEntry extends Entry<CacheInfo> {
1515
/// * [info]: The cache info
1616
/// * [value]: The cache value
1717
/// * [state]: The entry state
18-
CacheEntry._(CacheInfo info, dynamic value, EntryState state)
19-
: super(info, value, state);
18+
CacheEntry._(super.info, super.value, super.state);
2019

2120
/// Builds a new [CacheEntry]
2221
///
@@ -125,10 +124,8 @@ class CacheEntryBuilder<T> extends EntryBuilder<T, CacheInfo, CacheEntry> {
125124
/// * [accessTime]: The access time
126125
/// * [updateTime]: The update time
127126
CacheEntryBuilder(
128-
String key, T value, DateTime creationTime, this.expiryDuration,
129-
{this.hitCount, DateTime? accessTime, DateTime? updateTime})
130-
: super(key, value, creationTime,
131-
accessTime: accessTime, updateTime: updateTime);
127+
super.key, super.value, super.creationTime, this.expiryDuration,
128+
{this.hitCount, super.accessTime, super.updateTime});
132129

133130
@override
134131
CacheEntry build() {

packages/stash/lib/src/api/cache/cache_info.dart

+3-5
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,10 @@ class CacheInfo extends Info {
1616
/// * [hitCount]: The cache hit count
1717
/// * [accessTime]: The cache access time
1818
/// * [updateTime]: The cache update time
19-
CacheInfo(String key, DateTime creationTime, this.expiryTime,
20-
{int? hitCount, DateTime? accessTime, DateTime? updateTime})
19+
CacheInfo(super.key, super.creationTime, this.expiryTime,
20+
{int? hitCount, super.accessTime, super.updateTime})
2121
: assert(hitCount == null || hitCount >= 0),
22-
hitCount = hitCount ?? 0,
23-
super(key, creationTime,
24-
accessTime: accessTime, updateTime: updateTime);
22+
hitCount = hitCount ?? 0;
2523

2624
/// Checks if the cache info is expired
2725
///

packages/stash/lib/src/api/cache/cache_manager.dart

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ abstract class CacheManager {
2626
///
2727
/// * [store]: The [Store] that will back this [Cache]
2828
/// * [name]: The name of the cache
29+
/// * [fromEncodable]: The function that converts between the Map representation of the object and the object itself.
2930
/// * [expiryPolicy]: The expiry policy to use, defaults to [EternalExpiryPolicy] if not provided
3031
/// * [sampler]: The sampler to use upon eviction of a cache element, defaults to [FullSampler] if not provided
3132
/// * [evictionPolicy]: The eviction policy to use, defaults to [LruEvictionPolicy] if not provided
@@ -39,6 +40,7 @@ abstract class CacheManager {
3940
/// Returns a new DefaultCache
4041
Future<Cache<T>> newGenericCache<T>(Store<CacheInfo, CacheEntry> store,
4142
{String? name,
43+
dynamic Function(Map<String, dynamic>)? fromEncodable,
4244
ExpiryPolicy? expiryPolicy,
4345
KeySampler? sampler,
4446
EvictionPolicy? evictionPolicy,

packages/stash/lib/src/api/cache/event/event.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@ abstract class CacheEvent<T> extends StashEvent<T, CacheEventType, Cache<T>> {
2525
///
2626
/// * [source]: The cache that originated the event
2727
/// * [type]: The event type
28-
CacheEvent(Cache<T> source, CacheEventType type) : super(source, type);
28+
CacheEvent(super.source, super.type);
2929
}

packages/stash/lib/src/api/cache/manager/default_manager.dart

+4-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class DefaultCacheManager extends CacheManager {
2222
@override
2323
Future<Cache<T>> newGenericCache<T>(Store<CacheInfo, CacheEntry> store,
2424
{String? name,
25+
dynamic Function(Map<String, dynamic>)? fromEncodable,
2526
ExpiryPolicy? expiryPolicy,
2627
KeySampler? sampler,
2728
EvictionPolicy? evictionPolicy,
@@ -45,7 +46,9 @@ class DefaultCacheManager extends CacheManager {
4546
stats: stats);
4647
_caches[cache.name] = cache;
4748

48-
return store.create(cache.name).then((_) => cache);
49+
return store
50+
.create(cache.name, fromEncodable: fromEncodable)
51+
.then((_) => cache);
4952
}
5053

5154
@override

packages/stash/lib/src/api/store.dart

+71-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import 'package:meta/meta.dart';
2+
3+
import '../msgpack/codec.dart';
4+
import 'codec/store_codec.dart';
15
import 'entry.dart';
26
import 'info.dart';
37

@@ -6,14 +10,16 @@ abstract class Store<I extends Info, E extends Entry<I>> {
610
/// Creates a partition
711
///
812
/// * [name]: The partition name
9-
Future<void> create(String name);
13+
/// * [fromEncodable]: The function that converts between the Map representation of the object and the object itself.
14+
Future<void> create(String name,
15+
{dynamic Function(Map<String, dynamic>)? fromEncodable});
1016

1117
/// The number of entries in the partition
1218
///
1319
/// * [name]: The partition name
1420
Future<int> size(String name);
1521

16-
/// Returns a [Iterable] over all the keys
22+
/// Returns a [Iterable] over all the keys in the partition
1723
///
1824
/// * [name]: The partition name
1925
Future<Iterable<String>> keys(String name);
@@ -86,3 +92,66 @@ abstract class Store<I extends Info, E extends Entry<I>> {
8692
/// Deletes all partitions
8793
Future<void> deleteAll();
8894
}
95+
96+
/// A definition of a stores that persists data
97+
abstract class PersistenceStore<I extends Info, E extends Entry<I>>
98+
extends Store<I, E> {
99+
@protected
100+
101+
/// The store codec to use
102+
final StoreCodec codec;
103+
104+
/// Creates a [PersistenceStore].
105+
///
106+
/// * [codec]: The [StoreCodec] used to convert to/from a
107+
/// Map<String, dynamic>` representation to a binary representation.
108+
PersistenceStore({StoreCodec? codec}) : codec = codec ?? const MsgpackCodec();
109+
110+
/// Map of fromEncodable functions per partition
111+
final Map<String, dynamic Function(Map<String, dynamic>)> _fromEncodables =
112+
{};
113+
114+
/// Gets the partition `fromEncodable` function
115+
///
116+
/// * [name]: The partition name
117+
dynamic Function(Map<String, dynamic>)? decoder(String name) {
118+
return _fromEncodables[name];
119+
}
120+
121+
/// Decodes a value
122+
///
123+
/// * [value]: The value to decode
124+
/// * [fromEncodable]: The function that converts between the Map representation of the object and the object itself.
125+
/// * [mapFn]: A optional function that maps the value
126+
/// * [defaultFn]: A optional function that obtains the value to use in
127+
/// case there is no `fromEncodable` function for the partition
128+
dynamic decodeValue(
129+
dynamic value, dynamic Function(Map<String, dynamic>)? fromEncodable,
130+
{dynamic Function(dynamic)? mapFn, dynamic Function()? defaultFn}) {
131+
if (value == null) {
132+
return null;
133+
}
134+
135+
if (fromEncodable != null) {
136+
return fromEncodable(mapFn != null ? mapFn(value) : value);
137+
} else if (defaultFn != null) {
138+
return defaultFn();
139+
}
140+
141+
return value;
142+
}
143+
144+
/// Creates a partition
145+
///
146+
/// * [name]: The partition name
147+
/// * [fromEncodable]: The function that converts between the Map representation of the object and the object itself.
148+
@override
149+
Future<void> create(String name,
150+
{dynamic Function(Map<String, dynamic>)? fromEncodable}) {
151+
if (fromEncodable != null) {
152+
_fromEncodables[name] = fromEncodable;
153+
}
154+
155+
return Future.value();
156+
}
157+
}

packages/stash/lib/src/api/vault/event/event.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@ abstract class VaultEvent<T> extends StashEvent<T, VaultEventType, Vault<T>> {
1919
///
2020
/// * [source]: The vault that originated the event
2121
/// * [type]: The event type
22-
VaultEvent(Vault<T> source, VaultEventType type) : super(source, type);
22+
VaultEvent(super.source, super.type);
2323
}

packages/stash/lib/src/api/vault/manager/default_manager.dart

+4-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class DefaultVaultManager extends VaultManager {
1818
@override
1919
Future<Vault<T>> newGenericVault<T>(Store<VaultInfo, VaultEntry> store,
2020
{String? name,
21+
dynamic Function(Map<String, dynamic>)? fromEncodable,
2122
Clock? clock,
2223
EventListenerMode? eventListenerMode,
2324
bool? statsEnabled,
@@ -31,7 +32,9 @@ class DefaultVaultManager extends VaultManager {
3132
stats: stats);
3233
_vaults[vault.name] = vault;
3334

34-
return store.create(vault.name).then((_) => vault);
35+
return store
36+
.create(vault.name, fromEncodable: fromEncodable)
37+
.then((_) => vault);
3538
}
3639

3740
@override

packages/stash/lib/src/api/vault/vault_entry.dart

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ class VaultEntry extends Entry<VaultInfo> {
99
/// * [info]: The entry info
1010
/// * [value]: The entry value
1111
/// * [state]: The entry state
12-
VaultEntry._(VaultInfo info, dynamic value, EntryState state)
13-
: super(info, value, state);
12+
VaultEntry._(super.info, super.value, super.state);
1413

1514
/// Builds a new [VaultEntry]
1615
///

packages/stash/lib/src/api/vault/vault_info.dart

+2-4
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ class VaultInfo extends Info {
88
/// * [creationTime]: The vault creation time
99
/// * [accessTime]: The vault access time
1010
/// * [updateTime]: The vault update time
11-
VaultInfo(String key, DateTime creationTime,
12-
{int? type, DateTime? accessTime, DateTime? updateTime})
13-
: super(key, creationTime,
14-
accessTime: accessTime, updateTime: updateTime);
11+
VaultInfo(super.key, super.creationTime,
12+
{super.accessTime, super.updateTime});
1513
}

packages/stash/lib/src/api/vault/vault_manager.dart

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ abstract class VaultManager {
1919
///
2020
/// * [store]: The [Store] that will back this [Vault]
2121
/// * [name]: The name of the vault
22+
/// * [fromEncodable]: The function that converts between the Map representation of the object and the object itself.
2223
/// * [clock]: The source of time to be used on this, defaults to the system clock if not provided
2324
/// * [eventListenerMode]: The event listener mode of this vault
2425
/// * [statsEnabled]: If statistics should be collected, defaults to false
@@ -27,6 +28,7 @@ abstract class VaultManager {
2728
/// Returns a new [GenericVault]
2829
Future<Vault<T>> newGenericVault<T>(Store<VaultInfo, VaultEntry> store,
2930
{String? name,
31+
dynamic Function(Map<String, dynamic>)? fromEncodable,
3032
Clock? clock,
3133
EventListenerMode? eventListenerMode,
3234
bool? statsEnabled,

packages/stash/lib/src/msgpack/writer.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class MsgPackCyclicError extends MsgPackUnsupportedObjectError {
4646
/// Builds a [MsgPackCyclicError]
4747
///
4848
/// * [object]: The first object that was detected as part of a cycle.
49-
MsgPackCyclicError(Object object) : super(object);
49+
MsgPackCyclicError(super.object);
5050
@override
5151
String toString() => 'Cyclic error in JSON stringify';
5252
}
@@ -56,7 +56,7 @@ class MsgPackOverflowError extends MsgPackUnsupportedObjectError {
5656
/// Builds a [MsgPackOverflowError]
5757
///
5858
/// * [object]: The object that cannot be serialized.
59-
MsgPackOverflowError(Object object) : super(object);
59+
MsgPackOverflowError(super.object);
6060

6161
@override
6262
String toString() => 'Overflow error';

packages/stash/lib/stash_api.dart

+13-1
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,10 @@ Cache<T> newTieredCache<T>(
8989
extension VaultExtension on Store<VaultInfo, VaultEntry> {
9090
/// Creates a new [Vault] backed by a [Store]
9191
///
92-
/// * [manager]: An optional [VaultManager]
9392
/// * [store]: An existing store
93+
/// * [manager]: An optional [VaultManager]
9494
/// * [name]: The name of the vault
95+
/// * [fromEncodable]: The function that converts between the Map representation of the object and the object itself.
9596
/// * [eventListenerMode]: The event listener mode of this cache
9697
/// * [statsEnabled]: If statistics should be collected, defaults to false
9798
/// * [stats]: The statistics instance
@@ -100,11 +101,13 @@ extension VaultExtension on Store<VaultInfo, VaultEntry> {
100101
Future<Vault<T>> _newGenericVault<T>(Store<VaultInfo, VaultEntry> store,
101102
{VaultManager? manager,
102103
String? name,
104+
dynamic Function(Map<String, dynamic>)? fromEncodable,
103105
EventListenerMode? eventListenerMode,
104106
bool? statsEnabled,
105107
VaultStats? stats}) {
106108
return (manager ?? VaultManager.instance).newGenericVault<T>(store,
107109
name: name,
110+
fromEncodable: fromEncodable,
108111
eventListenerMode: eventListenerMode,
109112
statsEnabled: statsEnabled,
110113
stats: stats);
@@ -114,6 +117,7 @@ extension VaultExtension on Store<VaultInfo, VaultEntry> {
114117
///
115118
/// * [manager]: An optional [VaultManager]
116119
/// * [name]: The name of the vault
120+
/// * [fromEncodable]: The function that converts between the Map representation of the object and the object itself.
117121
/// * [eventListenerMode]: The event listener mode of this cache
118122
/// * [statsEnabled]: If statistics should be collected, defaults to false
119123
/// * [stats]: The statistics instance
@@ -122,12 +126,14 @@ extension VaultExtension on Store<VaultInfo, VaultEntry> {
122126
Future<Vault<T>> vault<T>(
123127
{VaultManager? manager,
124128
String? name,
129+
dynamic Function(Map<String, dynamic>)? fromEncodable,
125130
EventListenerMode? eventListenerMode,
126131
bool? statsEnabled,
127132
VaultStats? stats}) {
128133
return _newGenericVault<T>(this,
129134
manager: manager,
130135
name: name,
136+
fromEncodable: fromEncodable,
131137
eventListenerMode: eventListenerMode,
132138
statsEnabled: statsEnabled,
133139
stats: stats);
@@ -142,6 +148,7 @@ extension CacheExtension on Store<CacheInfo, CacheEntry> {
142148
/// * [store]: An existing store
143149
/// * [manager]: An optional [CacheManager]
144150
/// * [name]: The name of the cache
151+
/// * [fromEncodable]: The function that converts between the Map representation of the object and the object itself.
145152
/// * [expiryPolicy]: The expiry policy to use
146153
/// * [sampler]: The sampler to use upon eviction of a cache element
147154
/// * [evictionPolicy]: The eviction policy to use
@@ -153,6 +160,7 @@ extension CacheExtension on Store<CacheInfo, CacheEntry> {
153160
Future<Cache<T>> _newGenericCache<T>(Store<CacheInfo, CacheEntry> store,
154161
{CacheManager? manager,
155162
String? name,
163+
dynamic Function(Map<String, dynamic>)? fromEncodable,
156164
KeySampler? sampler,
157165
EvictionPolicy? evictionPolicy,
158166
int? maxEntries,
@@ -163,6 +171,7 @@ extension CacheExtension on Store<CacheInfo, CacheEntry> {
163171
CacheStats? stats}) {
164172
return (manager ?? CacheManager.instance).newGenericCache<T>(store,
165173
name: name,
174+
fromEncodable: fromEncodable,
166175
expiryPolicy: expiryPolicy,
167176
sampler: sampler,
168177
evictionPolicy: evictionPolicy,
@@ -177,6 +186,7 @@ extension CacheExtension on Store<CacheInfo, CacheEntry> {
177186
///
178187
/// * [manager]: An optional [CacheManager]
179188
/// * [name]: The name of the cache
189+
/// * [fromEncodable]: The function that converts between the Map representation of the object and the object itself.
180190
/// * [expiryPolicy]: The expiry policy to use
181191
/// * [sampler]: The sampler to use upon eviction of a cache element
182192
/// * [evictionPolicy]: The eviction policy to use
@@ -190,6 +200,7 @@ extension CacheExtension on Store<CacheInfo, CacheEntry> {
190200
Future<Cache<T>> cache<T>(
191201
{CacheManager? manager,
192202
String? name,
203+
dynamic Function(Map<String, dynamic>)? fromEncodable,
193204
KeySampler? sampler,
194205
EvictionPolicy? evictionPolicy,
195206
int? maxEntries,
@@ -201,6 +212,7 @@ extension CacheExtension on Store<CacheInfo, CacheEntry> {
201212
return _newGenericCache<T>(this,
202213
manager: manager,
203214
name: name,
215+
fromEncodable: fromEncodable,
204216
expiryPolicy: expiryPolicy,
205217
sampler: sampler,
206218
evictionPolicy: evictionPolicy,

packages/stash_cbl/README.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,13 @@ void main() async {
9191
final path = Directory.systemTemp.path;
9292
9393
// Creates a store
94-
final store = await newCblLocalVaultStore(
95-
path: path, fromEncodable: (json) => Task.fromJson(json));
94+
final store = await newCblLocalVaultStore(path: path);
9695
9796
// Creates a vault from the previously created store
9897
final vault = await store.vault<Task>(
99-
name: 'vault', eventListenerMode: EventListenerMode.synchronous)
98+
name: 'vault',
99+
fromEncodable: (json) => Task.fromJson(json),
100+
eventListenerMode: EventListenerMode.synchronous)
100101
..on<VaultEntryCreatedEvent<Task>>().listen(
101102
(event) => print('Key "${event.entry.key}" added to the vault'));
102103

packages/stash_cbl/example/cache/example.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ void main() async {
3535
final path = Directory.systemTemp.path;
3636

3737
// Creates a store
38-
final store = await newCblLocalCacheStore(
39-
path: path, fromEncodable: (json) => Task.fromJson(json));
38+
final store = await newCblLocalCacheStore(path: path);
4039

4140
// Creates a cache with a capacity of 10 from the previously created store
4241
final cache = await store.cache<Task>(
4342
name: 'cache1',
43+
fromEncodable: (json) => Task.fromJson(json),
4444
maxEntries: 10,
4545
eventListenerMode: EventListenerMode.synchronous)
4646
..on<CacheEntryCreatedEvent<Task>>().listen(

0 commit comments

Comments
 (0)