-
-
Notifications
You must be signed in to change notification settings - Fork 3
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
Does not work with embedded objects #12
Comments
@eelco2k could you please share the example of how you are using the package? |
@richard457 i was now testing it in a simpeler sample project here is my setup: pubspec dependencies:
lib/models/cars.dart import 'package:isar/isar.dart';
import 'package:isar_crdt/isar_crdt.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:uuid/uuid.dart';
part 'cars.g.dart';
var uuid = const Uuid();
@JsonSerializable(explicitToJson: true)
@Collection()
class Cars extends CrdtBaseObject {
Id? id = Isar.autoIncrement;
String? make;
CarModel? model;
int? year;
Cars({this.id, this.make, this.model, this.year});
factory Cars.fromJson(Map<String, dynamic> json) => _$CarsFromJson(json);
Map<String, dynamic> toJson() => _$CarsToJson(this);
}
@JsonSerializable(explicitToJson: true)
@Embedded()
class CarModel {
String? productUuid = uuid.v4();
String? name;
List<String>? features;
CarModel({
this.productUuid,
this.name,
this.features,
});
factory CarModel.fromJson(Map<String, dynamic> json) => _$CarModelFromJson(json);
Map<String, dynamic> toJson() => _$CarModelToJson(this);
}
@Collection()
class CrdtEntry extends CrdtBaseModel {} lib/main.dart of the flutter counter sample app i reuse the incrementCounter function to start crdt delayed inserts class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
late Isar isar;
void _initDB() async {
final dir = await getApplicationDocumentsDirectory();
isar = await Isar.open(
[CarsSchema, CrdtEntrySchema],
directory: dir.path,
);
}
void _incrementCounter() {
startIsarDb();
setState(() {
_counter++;
});
}
void startIsarDb() async {
var uuid = const Uuid();
IsarCrdt crdt;
String nodeId = 'test-nodeid';
String remoteNodeId = 'test-nodeid-remote';
String workspace = 'test-workspace';
crdt = IsarCrdt.master(
crdtCollection: isar.crdtEntrys,
builder: () => Future.value(CrdtEntry()),
sidGenerator: () => uuid.v4(),
nodeId: nodeId,
);
isar.setCrdt(crdt);
String theSid = uuid.v4();
int firstCar = 1;
Future.delayed(const Duration(milliseconds: 2000), () async {
final lateCar = Cars()
..make = 'Nissan'
..sid = theSid
..year = 2014;
final model = CarModel()
..name = "Quashqai"
..features = ["1.4 liter", "petrol", "manual gearbox"];
lateCar.model = model;
await crdt.writer?.writeTxn(() async {
final carCollection = isar.collection<Cars>();
firstCar = await carCollection.putChanges(lateCar);
});
});
Future.delayed(const Duration(milliseconds: 4000), () async {
final carCollection = isar.cars;
var thecar = await carCollection.get(firstCar);
thecar?.make = 'Toyota';
thecar?.sid = theSid;
thecar?.year = 2017;
thecar?.model?.name = "Passat";
await crdt.writer?.writeTxn(() async {
// print(thecar);
await carCollection.putChanges(thecar!);
});
});
Future.delayed(const Duration(milliseconds: 5000), () async {
final carCollection = isar.cars;
var thecar = await carCollection.get(firstCar);
List<String>? currFeatures = thecar?.model?.features.toList();
currFeatures!.add("another extra Feature");
thecar?.model?.features = currFeatures;
await crdt.writer?.writeTxn(() async {
// print(thecar);
await carCollection.putChanges(thecar!);
});
});
// merge everything....
Future.delayed(const Duration(milliseconds: 6000), () async {
final changes = await crdt.getChanges(onlyModifiedHere: true);
// final carCollection = isar.collection<Cars>();
List<MergableChange> syncChanges = [];
for (var change in changes) {
// print(change.toJson());
syncChanges.add(MergableChange(change: change.change, hlc: change.hlc));
}
// print(syncChanges);
crdt.writer?.upgradeChanges(changes);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(onPressed: _initDB, child: const Text('Init DB')),
const SizedBox(height: 10),
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
you would expect that: gives crdtEntry only on the added "another extra Feature" but it says it added the whole features which is not correct. So the @Embedded wil work but not as I was expecting. Because when you use multiple parent -> child -> child -> child. as inner embeddings it gets worse. |
This is the resulting CrdtEntry Table as you can see a whole update on the "another extra Feature" item: collection: "Cars", which is actually incorrect and should be: collection:"CarModel", So single level depth(s) for each Collection is no problem for this package isar_crdt, but when you use objects in objects in one and the same collection (table) this will not work correctly. |
I'm not maintaining this project as Isar was not the best option to manage this crdt changes |
Unfortunately it does not work with @Embedded objects. It just sees it as an insert.
(for .toJson() i'm using the json_annotation package)
for example:
It inserts the whole json ( .toJson() ) in the crdt entries table (value column) as 1 crdt event.
So i guess it only works with the Int, String, and simple Lists..
Furthermore what could be the case is that it needs an id autoIncrement which this embedded object does not have.
in isar_extensions.dart the putAllChanges() relies on schema.getId() for new and changed entries.
specific:
The text was updated successfully, but these errors were encountered: