Skip to content

Commit

Permalink
feat: Addition of Batch processing and addition to transaction to Col…
Browse files Browse the repository at this point in the history
…lection.
  • Loading branch information
mathrunet committed Aug 6, 2023
1 parent 00c5203 commit 9e669b7
Show file tree
Hide file tree
Showing 14 changed files with 801 additions and 101 deletions.
51 changes: 47 additions & 4 deletions packages/katana_model/lib/adapter/runtime_model_adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -196,20 +196,54 @@ class RuntimeModelAdapter extends ModelAdapter {
}

@override
FutureOr<void> runTransaction<T>(
DocumentBase<T> doc,
FutureOr<void> runTransaction(
FutureOr<void> Function(
ModelTransactionRef ref,
ModelTransactionDocument<T> doc,
) transaction,
) async {
final ref = RuntimeModelTransactionRef._();
await transaction.call(ref, ref.read(doc));
await transaction.call(ref);
for (final tmp in ref._transactionList) {
await tmp.call();
}
}

@override
void deleteOnBatch(
ModelBatchRef ref,
ModelAdapterDocumentQuery query,
) {
if (ref is! RuntimeModelBatchRef) {
throw Exception("[ref] is not [RuntimeModelBatchRef].");
}
ref._batchList.add(() => deleteDocument(query));
}

@override
void saveOnBatch(
ModelBatchRef ref,
ModelAdapterDocumentQuery query,
DynamicMap value,
) {
if (ref is! RuntimeModelBatchRef) {
throw Exception("[ref] is not [RuntimeModelBatchRef].");
}
ref._batchList.add(() => saveDocument(query, value));
}

@override
FutureOr<void> runBatch(
FutureOr<void> Function(
ModelBatchRef ref,
) batch,
int splitLength,
) async {
final ref = RuntimeModelBatchRef._();
await wait(
ref._batchList.map((tmp) => tmp.call()),
);
}

String _path(String original) {
if (prefix.isEmpty) {
return original;
Expand All @@ -236,3 +270,12 @@ class RuntimeModelTransactionRef extends ModelTransactionRef {

final List<FutureOr<void> Function()> _transactionList = [];
}

/// [ModelBatchRef] for [RuntimeModelAdapter].
/// [RuntimeModelAdapter]用の[ModelBatchRef]
@immutable
class RuntimeModelBatchRef extends ModelBatchRef {
RuntimeModelBatchRef._();

final List<FutureOr<void> Function()> _batchList = [];
}
1 change: 1 addition & 0 deletions packages/katana_model/lib/katana_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ part 'src/model_query.dart';
part 'src/model_locale.dart';
part 'src/collection_base.dart';
part 'src/listenable_listener.dart';
part 'src/model_batch.dart';
part 'src/model_transaction.dart';
part 'src/model_field_value.dart';
part 'src/model_geo_value.dart';
Expand Down
28 changes: 28 additions & 0 deletions packages/katana_model/lib/src/collection_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,34 @@ abstract class CollectionBase<TModel extends DocumentBase>
return loaded;
}

/// {@macro model_transaction}
///
/// ```dart
/// final transaction = sourceCollection.transaction();
/// transaction((ref, collection){
/// final doc = ref.read(collection.create()); // `doc` is [ModelTransactionDocument] of `sourceDocument`.
/// final newValue = {"name": "test"}; // The same mechanism can be used to perform the same preservation method as usual.
/// doc.save(newValue);
/// });
/// ```
ModelTransactionCollectionBuilder<TModel> transaction() {
return ModelTransactionCollectionBuilder._(this);
}

/// {@macro model_batch}
///
/// ```dart
/// final batch = sourceCollection.batch();
/// batch((ref, collection){
/// final doc = ref.read(collection.create()); // `doc` is [ModelBatchDocument] of `sourceDocument`.
/// final newValue = {"name": "test"}; // The same mechanism can be used to perform the same preservation method as usual.
/// doc.save(newValue);
/// });
/// ```
ModelBatchCollectionBuilder<TModel> batch({int splitLength = 100}) {
return ModelBatchCollectionBuilder._(this, splitLength);
}

/// [callback] will redefine a new [CollectionModelQuery] and execute [reload].
///
/// Use this function when you want to read the file again with new conditions.
Expand Down
41 changes: 23 additions & 18 deletions packages/katana_model/lib/src/document_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ part of katana_model;
///
/// Any changes made locally in the app will be notified and related objects will reflect the changes.
///
/// When a value is reflected by [save], [delete], [transaction], or updated in real time from outside, all listeners are notified of the change by [notifyListeners].
/// When a value is reflected by [save], [delete], [transaction], [batch], or updated in real time from outside, all listeners are notified of the change by [notifyListeners].
///
/// Define object conversion from [DynamicMap] to [T], which is output by decoding Json by implementing [DocumentBase.fromMap].
///
Expand All @@ -18,7 +18,7 @@ part of katana_model;
///
/// アプリのローカル内での変更はすべて通知され関連のあるオブジェクトは変更内容が反映されます。
///
/// [save][delete][transaction]での値反映、外部からのリアルタイム更新が行われた場合[notifyListeners]によって変更内容がすべてのリスナーに通知されます。
/// [save][delete][transaction][batch]での値反映、外部からのリアルタイム更新が行われた場合[notifyListeners]によって変更内容がすべてのリスナーに通知されます。
///
/// [DocumentBase.fromMap]を実装することでJsonをデコードして出力される[DynamicMap]から[T]へのオブジェクト変換を定義します。
///
Expand All @@ -33,7 +33,7 @@ abstract class DocumentBase<T> extends ChangeNotifier
///
/// Any changes made locally in the app will be notified and related objects will reflect the changes.
///
/// When a value is reflected by [save], [delete], [transaction], or updated in real time from outside, all listeners are notified of the change by [notifyListeners].
/// When a value is reflected by [save], [delete], [transaction], [batch], or updated in real time from outside, all listeners are notified of the change by [notifyListeners].
///
/// Define object conversion from [DynamicMap] to [T], which is output by decoding Json by implementing [DocumentBase.fromMap].
///
Expand All @@ -47,7 +47,7 @@ abstract class DocumentBase<T> extends ChangeNotifier
///
/// アプリのローカル内での変更はすべて通知され関連のあるオブジェクトは変更内容が反映されます。
///
/// [save][delete][transaction]での値反映、外部からのリアルタイム更新が行われた場合[notifyListeners]によって変更内容がすべてのリスナーに通知されます。
/// [save][delete][transaction][batch]での値反映、外部からのリアルタイム更新が行われた場合[notifyListeners]によって変更内容がすべてのリスナーに通知されます。
///
/// [DocumentBase.fromMap]を実装することでJsonをデコードして出力される[DynamicMap]から[T]へのオブジェクト変換を定義します。
///
Expand Down Expand Up @@ -336,27 +336,32 @@ abstract class DocumentBase<T> extends ChangeNotifier
}
}

/// Create a transaction builder.
///
/// The invoked transaction can be `call` as is, and transaction processing can be performed by executing [ModelTransactionDocument.load], [ModelTransactionDocument.save], and [ModelTransactionDocument.delete].
///
/// ModelTransactionRef.read] can be used to create a [ModelTransactionDocument] from another [DocumentBase] and describe the process to be performed together.
///
/// トランザクションビルダーを作成します。
///
/// 呼び出されたトランザクションはそのまま`call`することができ、その引数から与えられる[ModelTransactionDocument]を用いて[ModelTransactionDocument.load][ModelTransactionDocument.save][ModelTransactionDocument.delete]を実行することでトランザクション処理を行うことが可能です。
///
/// [ModelTransactionRef.read]を用いて他の[DocumentBase]から[ModelTransactionDocument]を作成することができ、まとめて実行する処理を記述することができます。
/// {@macro model_transaction}
///
/// ```dart
/// final transaction = sourceDocument.transaction();
/// transaction((ref, doc){ // `doc`は`sourceDocument`の[ModelTransactionDocument]
/// transaction((ref, document){
/// final doc = ref.read(document); // `doc` is [ModelTransactionDocument] of `sourceDocument`.
/// final newValue = {"name": "test"}; // The same mechanism can be used to perform the same preservation method as usual.
/// doc.save(newValue);
/// });
/// ```
ModelTransactionDocumentBuilder<T> transaction() {
return ModelTransactionDocumentBuilder._(this);
}

/// {@macro model_batch}
///
/// ```dart
/// final batch = sourceDocument.batch();
/// batch((ref, document){
/// final doc = ref.read(document); // `doc` is [ModelBatchDocument] of `sourceDocument`.
/// final newValue = {"name": "test"}; // The same mechanism can be used to perform the same preservation method as usual.
/// doc.save(newValue);
/// });
/// ```
ModelTransactionBuilder<T> transaction() {
return ModelTransactionBuilder._(this);
ModelBatchDocumentBuilder<T> batch({int splitLength = 100}) {
return ModelBatchDocumentBuilder._(this, splitLength);
}

/// Implement internal processing when [load] or [reload] is executed.
Expand Down
63 changes: 54 additions & 9 deletions packages/katana_model/lib/src/model_adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -185,20 +185,14 @@ abstract class ModelAdapter {

/// Do the processing to execute the transaction.
///
/// The base document is passed to [doc] and the actual processing callback is passed to [transaction].
///
/// Create an adapter-specific [ModelTransactionRef] that internally inherits from [ModelTransactionRef], create a [doc] from that [ModelTransactionRef.read], pass it directly to the [transaction] argument, and execute [transaction].
/// Create an adapter-specific [ModelTransactionRef] that internally inherits from [ModelTransactionRef], create a [ModelTransactionDocument] from that [ModelTransactionRef.read], pass it directly to the TransactionRef], create a [ModelTransactionDocument] from that [ModelTransactionRef.read], pass it directly to the [transaction] argument, and then execute the [transaction].
///
/// トランザクションを実行するための処理を行います。
///
/// [doc]にベースとなるドキュメントが渡され、[transaction]に実際行われる処理のコールバックが渡されます。
///
/// 内部で[ModelTransactionRef]を継承したアダプター専用の[ModelTransactionRef]を作成し、その[ModelTransactionRef.read]から[doc]を作成、それをそのまま[transaction]の引数に渡し、[transaction]を実行するようにしてください。
FutureOr<void> runTransaction<T>(
DocumentBase<T> doc,
/// 内部で[ModelTransactionRef]を継承したアダプター専用の[ModelTransactionRef]を作成し、その[ModelTransactionRef.read]から[ModelTransactionDocument]を作成、それをそのまま[transaction]の引数に渡し、[transaction]を実行するようにしてください。
FutureOr<void> runTransaction(
FutureOr<void> Function(
ModelTransactionRef ref,
ModelTransactionDocument<T> doc,
) transaction,
);

Expand Down Expand Up @@ -250,6 +244,57 @@ abstract class ModelAdapter {
ModelTransactionRef ref,
ModelAdapterDocumentQuery query,
);

/// Processes a batch for execution.
///
/// Create an adapter-specific [ModelBatchRef] that inherits [ModelBatchRef] internally, create a [ModelBatchDocument] from the [ModelBatchRef.read], pass it as an argument to [batch], and execute [batch batch] and execute [batch].
///
/// Split batches by specifying [splitLength].
///
/// バッチを実行するための処理を行います。
///
/// 内部で[ModelBatchRef]を継承したアダプター専用の[ModelBatchRef]を作成し、その[ModelBatchRef.read]から[ModelBatchDocument]を作成、それをそのまま[batch]の引数に渡し、[batch]を実行するようにしてください。
///
/// [splitLength]を指定してバッチを分割することができます。
FutureOr<void> runBatch(
FutureOr<void> Function(
ModelBatchRef ref,
) batch,
int splitLength,
);

/// Describe the data storage process when performing a batch.
///
/// The [ModelBatchRef] created by [runBatch] is passed to [ref], and [query] is the query of the target document.
///
/// The data to be stored is passed to [value].
///
/// Keys with [value] value of [null] should be deleted from the database.
///
/// バッチを行う際のデータ保存処理を記述します。
///
/// [ref][runBatch]で作成した[ModelBatchRef]が渡され、[query]は対象のドキュメントのクエリが渡されます。
///
/// [value]に保存するデータが渡されます。
///
/// [value]の値に[Null]が入っているキーはデータベース上から削除するようにしてください。
void saveOnBatch(
ModelBatchRef ref,
ModelAdapterDocumentQuery query,
DynamicMap value,
);

/// Describe the data deletion process when performing a batch.
///
/// The [ModelBatchRef] created by [runBatch] is passed to [ref], and [query] is the query of the target document.
///
/// バッチを行う際のデータ削除処理を記述します。
///
/// [ref][runBatch]で作成した[ModelBatchRef]が渡され、[query]は対象のドキュメントのクエリが渡されます。
void deleteOnBatch(
ModelBatchRef ref,
ModelAdapterDocumentQuery query,
);
}

/// Widget for setting [ModelAdapter].
Expand Down
Loading

0 comments on commit 9e669b7

Please sign in to comment.