Skip to content

Commit 1c6c623

Browse files
committed
Remove streaming from database from export operation
1 parent 3d7ee16 commit 1c6c623

File tree

2 files changed

+102
-128
lines changed

2 files changed

+102
-128
lines changed

lib/src/backend/impls/objectbox/backend/backend.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ import 'dart:isolate';
99
import 'dart:math';
1010

1111
import 'package:collection/collection.dart';
12-
import 'package:flutter/material.dart';
12+
import 'package:flutter/foundation.dart';
1313
import 'package:flutter/services.dart';
14-
import 'package:meta/meta.dart';
1514
import 'package:path/path.dart' as path;
1615
import 'package:path_provider/path_provider.dart';
1716

lib/src/backend/impls/objectbox/backend/internal_workers/standard/worker.dart

Lines changed: 101 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -900,142 +900,117 @@ Future<void> _worker(
900900
rethrow;
901901
}
902902

903-
final storesQuery = root
904-
.box<ObjectBoxStore>()
905-
.query(ObjectBoxStore_.name.oneOf(storeNames))
906-
.build();
903+
try {
904+
final storesQuery = root
905+
.box<ObjectBoxStore>()
906+
.query(ObjectBoxStore_.name.oneOf(storeNames))
907+
.build();
908+
final tilesQuery = (root.box<ObjectBoxTile>().query()
909+
..linkMany(
910+
ObjectBoxTile_.stores,
911+
ObjectBoxStore_.name.oneOf(storeNames),
912+
))
913+
.build();
907914

908-
final tilesQuery = (root.box<ObjectBoxTile>().query()
909-
..linkMany(
910-
ObjectBoxTile_.stores,
911-
ObjectBoxStore_.name.oneOf(storeNames),
912-
))
913-
.build();
915+
// Copy all stores to external root
916+
// Then, to make sure relations work 100%, we go through the stores
917+
// just copied to the external root and add them to the map below
918+
final storesToExport = storesQuery.find();
919+
if (!listEquals(
920+
storesToExport.map((s) => s.name).toList(growable: false),
921+
storeNames,
922+
)) {
923+
throw ArgumentError(
924+
'Specified stores did not match the resolved existing stores',
925+
'storeNames',
926+
);
927+
}
928+
final storesObjectsForRelations =
929+
Map<String, ObjectBoxStore>.fromEntries(
930+
(exportingRoot.box<ObjectBoxStore>()
931+
..putMany(
932+
storesQuery
933+
.find()
934+
.map(
935+
(store) => ObjectBoxStore(
936+
name: store.name,
937+
maxLength: store.maxLength,
938+
length: store.length,
939+
size: store.size,
940+
hits: store.hits,
941+
misses: store.misses,
942+
metadataJson: store.metadataJson,
943+
),
944+
)
945+
.toList(growable: false),
946+
mode: PutMode.insert,
947+
))
948+
.getAll()
949+
.map((s) => MapEntry(s.name, s)),
950+
);
914951

915-
final storesObjectsForRelations = <String, ObjectBoxStore>{};
952+
// Copy all tiles to external root
953+
int numExportedTiles = 0;
954+
tilesQuery.chunkedMultiTransaction(
955+
chunkSize: 300,
956+
root: root,
957+
runInTransaction: (tile) {
958+
exportingRoot.box<ObjectBoxTile>().put(
959+
ObjectBoxTile(
960+
url: tile.url,
961+
bytes: tile.bytes,
962+
lastModified: tile.lastModified,
963+
)..stores.addAll(
964+
tile.stores
965+
.map((s) => storesObjectsForRelations[s.name])
966+
.nonNulls,
967+
),
968+
mode: PutMode.insert,
969+
);
970+
numExportedTiles++;
971+
},
972+
);
916973

917-
final exportingStores = root.runInTransaction(
918-
TxMode.read,
919-
storesQuery.stream,
920-
);
974+
storesQuery.close();
975+
tilesQuery.close();
976+
exportingRoot.close();
921977

922-
exportingRoot
923-
.runInTransaction(
924-
TxMode.write,
925-
() => exportingStores.map(
926-
(exportingStore) {
927-
exportingRoot.box<ObjectBoxStore>().put(
928-
storesObjectsForRelations[exportingStore.name] =
929-
ObjectBoxStore(
930-
name: exportingStore.name,
931-
maxLength: exportingStore.maxLength,
932-
length: exportingStore.length,
933-
size: exportingStore.size,
934-
hits: exportingStore.hits,
935-
misses: exportingStore.misses,
936-
metadataJson: exportingStore.metadataJson,
937-
),
938-
mode: PutMode.insert,
939-
);
940-
},
941-
),
942-
)
943-
.length
944-
.then(
945-
(numExportedStores) {
946-
if (numExportedStores == 0) throw StateError('Unpossible');
947-
948-
final exportingTiles = root.runInTransaction(
949-
TxMode.read,
950-
tilesQuery.stream,
951-
);
978+
final dbFile = File(path.join(workingDir.absolute.path, 'data.mdb'));
952979

953-
exportingRoot
954-
.runInTransaction(
955-
TxMode.write,
956-
() => exportingTiles.map(
957-
(exportingTile) {
958-
exportingRoot.box<ObjectBoxTile>().put(
959-
ObjectBoxTile(
960-
url: exportingTile.url,
961-
bytes: exportingTile.bytes,
962-
lastModified: exportingTile.lastModified,
963-
)..stores.addAll(
964-
exportingTile.stores
965-
.map(
966-
(s) => storesObjectsForRelations[s.name],
967-
)
968-
.nonNulls,
969-
),
970-
mode: PutMode.insert,
971-
);
972-
},
973-
),
974-
)
975-
.length
976-
.then(
977-
(numExportedTiles) {
978-
if (numExportedTiles == 0) {
979-
throw ArgumentError(
980-
'Specified stores must include at least one tile total',
981-
'storeNames',
982-
);
983-
}
980+
final ram = dbFile.openSync(mode: FileMode.writeOnlyAppend);
981+
try {
982+
ram
983+
..writeFromSync(List.filled(4, 255))
984+
..writeStringSync('ObjectBox') // Backend identifier
985+
..writeByteSync(255)
986+
..writeByteSync(255)
987+
..writeStringSync('FMTC'); // Signature
988+
} finally {
989+
ram.closeSync();
990+
}
984991

985-
storesQuery.close();
986-
tilesQuery.close();
987-
exportingRoot.close();
988-
989-
final dbFile =
990-
File(path.join(workingDir.absolute.path, 'data.mdb'));
991-
992-
final ram = dbFile.openSync(mode: FileMode.writeOnlyAppend);
993-
try {
994-
ram
995-
..writeFromSync(List.filled(4, 255))
996-
..writeStringSync('ObjectBox') // Backend identifier
997-
..writeByteSync(255)
998-
..writeByteSync(255)
999-
..writeStringSync('FMTC'); // Signature
1000-
} finally {
1001-
ram.closeSync();
1002-
}
992+
try {
993+
dbFile.renameSync(outputPath);
994+
} on FileSystemException {
995+
dbFile.copySync(outputPath);
996+
} finally {
997+
workingDir.deleteSync(recursive: true);
998+
}
1003999

1004-
try {
1005-
dbFile.renameSync(outputPath);
1006-
} on FileSystemException {
1007-
dbFile.copySync(outputPath);
1008-
} finally {
1009-
workingDir.deleteSync(recursive: true);
1010-
}
1000+
sendRes(
1001+
id: cmd.id,
1002+
data: {'numExportedTiles': numExportedTiles},
1003+
);
10111004

1012-
sendRes(
1013-
id: cmd.id,
1014-
data: {'numExportedTiles': numExportedTiles},
1015-
);
1016-
},
1017-
).catchError((error, stackTrace) {
1018-
exportingRoot.close();
1019-
try {
1020-
workingDir.deleteSync(recursive: true);
1021-
// If the working dir didn't exist, that's fine
1022-
// We don't want to spend time checking if exists, as it likely
1023-
// does
1024-
// ignore: empty_catches
1025-
} on FileSystemException {}
1026-
Error.throwWithStackTrace(error, stackTrace);
1027-
});
1028-
},
1029-
).catchError((error, stackTrace) {
1005+
// We don't care what type, we always need to clean up and rethrow
1006+
// ignore: avoid_catches_without_on_clauses
1007+
} catch (e) {
10301008
exportingRoot.close();
1031-
try {
1009+
if (workingDir.existsSync()) {
10321010
workingDir.deleteSync(recursive: true);
1033-
// If the working dir didn't exist, that's fine
1034-
// We don't want to spend time checking if exists, as it likely does
1035-
// ignore: empty_catches
1036-
} on FileSystemException {}
1037-
Error.throwWithStackTrace(error, stackTrace);
1038-
});
1011+
}
1012+
rethrow;
1013+
}
10391014
case _CmdType.importStores:
10401015
final importPath = cmd.args['path']! as String;
10411016
final strategy = cmd.args['strategy'] as ImportConflictStrategy;

0 commit comments

Comments
 (0)