diff --git a/hive/CHANGELOG.md b/hive/CHANGELOG.md index bce12921..586c7665 100644 --- a/hive/CHANGELOG.md +++ b/hive/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.19.3 + +- IsolatedHive: Handles stale send ports on hot restart + ## 2.19.2 - Updates `isolate_channel` to `0.6.0` diff --git a/hive/lib/src/isolate/isolated_hive_impl/impl/isolated_hive_impl_vm.dart b/hive/lib/src/isolate/isolated_hive_impl/impl/isolated_hive_impl_vm.dart index 744246ae..f2cbeeca 100644 --- a/hive/lib/src/isolate/isolated_hive_impl/impl/isolated_hive_impl_vm.dart +++ b/hive/lib/src/isolate/isolated_hive_impl/impl/isolated_hive_impl_vm.dart @@ -9,6 +9,7 @@ import 'package:hive_ce/src/isolate/isolated_box_impl/isolated_box_impl_vm.dart' import 'package:hive_ce/src/isolate/isolated_hive_impl/hive_isolate.dart'; import 'package:hive_ce/src/isolate/isolated_hive_impl/hive_isolate_name.dart'; import 'package:hive_ce/src/registry/type_registry_impl.dart'; +import 'package:hive_ce/src/util/debug_utils.dart'; import 'package:hive_ce/src/util/logger.dart'; import 'package:hive_ce/src/util/type_utils.dart'; import 'package:isolate_channel/isolate_channel.dart'; @@ -38,8 +39,10 @@ class IsolatedHiveImpl extends TypeRegistryImpl ); @override - void onConnect(SendPort send) => - _isolateNameServer?.registerPortWithName(send, hiveIsolateName); + void onConnect(SendPort send) { + _isolateNameServer?.removePortNameMapping(hiveIsolateName); + _isolateNameServer?.registerPortWithName(send, hiveIsolateName); + } @override void onExit() => _isolateNameServer?.removePortNameMapping(hiveIsolateName); @@ -63,9 +66,22 @@ class IsolatedHiveImpl extends TypeRegistryImpl final send = _isolateNameServer?.lookupPortByName(hiveIsolateName) as SendPort?; - final IsolateConnection connection; + IsolateConnection connection; if (send != null) { - connection = await connectToIsolate(send); + try { + var connectFuture = connectToIsolate(send); + + // Sometimes the INS does not get cleared on a hot restart + // This results in the send port being stale + // This would be unsafe in release mode + if (kDebugMode) { + connectFuture = + connectFuture.timeout(const Duration(milliseconds: 250)); + } + connection = await connectFuture; + } on TimeoutException { + connection = await _spawnHiveIsolate(); + } } else { connection = await _spawnHiveIsolate(); } diff --git a/hive/pubspec.yaml b/hive/pubspec.yaml index 4f161446..f26c47a9 100644 --- a/hive/pubspec.yaml +++ b/hive/pubspec.yaml @@ -1,6 +1,6 @@ name: hive_ce description: Hive Community Edition - A spiritual continuation of Hive v2 -version: 2.19.2 +version: 2.19.3 homepage: https://github.com/IO-Design-Team/hive_ce/tree/main/hive topics: diff --git a/hive/test/integration/isolate_test.dart b/hive/test/integration/isolate_test.dart index 2531d81c..14fde219 100644 --- a/hive/test/integration/isolate_test.dart +++ b/hive/test/integration/isolate_test.dart @@ -8,6 +8,7 @@ import 'package:hive_ce/hive_ce.dart'; import 'package:hive_ce/src/hive_impl.dart'; import 'package:hive_ce/src/isolate/handler/isolate_entry_point.dart'; import 'package:hive_ce/src/isolate/isolated_hive_impl/hive_isolate.dart'; +import 'package:hive_ce/src/isolate/isolated_hive_impl/hive_isolate_name.dart'; import 'package:hive_ce/src/isolate/isolated_hive_impl/isolated_hive_impl.dart'; import 'package:hive_ce/src/util/logger.dart'; import 'package:isolate_channel/isolate_channel.dart'; @@ -366,6 +367,25 @@ void main() { ); expect(await box.get('key'), 'value'); }); + + test('Stale send port', () async { + final dir = await getTempDir(); + final hive = IsolatedHiveImpl(); + addTearDown(hive.close); + + final ins = TestIns(); + ins.registerPortWithName(ReceivePort().sendPort, hiveIsolateName); + + var spawned = false; + (hive as HiveIsolate).spawnHiveIsolate = () { + spawned = true; + return spawnIsolate(isolateEntryPoint); + }; + + await hive.init(dir.path, isolateNameServer: ins); + + expect(spawned, isTrue); + }); }, onPlatform: { 'chrome': Skip('Isolates are not supported on web'),