objectbox / objectbox/objectbox-dart

[Flutter] query.watch() never seems to close the underlying query

Open
#448 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

needs more interest
Dominant language
Dart
Stars
1.2k
Forks
162
Avg merge
15m
Merged PRs (30d)
1

Description

When using query(condition).watch() you get a Stream of changes. However, there does not seem to be a way to close the underlying query.

As stated in the docs for Query, we should close the query when we are done with it.

Call [Query.close()] after you're done with it to free resources.

However the underlying StreamController only calls subscription.cancel() and not query.close() when it is closed.

Basic info (please complete the following information):
  • ObjectBox version: 1.6.0
  • Flutter/Dart SDK: Flutter 3.0.2 / Dart 2.17.3
  • Null-safety enabled: yes
  • Reproducibility: always
  • OS: MacOS 12.2.1
  • Device/Emulator: N/A

Additionally, you can choose to provide more details, e.g. the output of:

  • flutter doctor -v
[✓] Flutter (Channel stable, 3.0.2, on macOS 12.2.1 21D62 darwin-x64, locale
    en-BE)
    • Flutter version 3.0.2 at /Users/navaronbracke/Documents/flutter
    • Upstream repository git@github.com:flutter/flutter.git
    • Framework revision cd41fdd495 (7 weeks ago), 2022-06-08 09:52:13 -0700
    • Engine revision f15f824b57
    • Dart version 2.17.3
    • DevTools version 2.12.2

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    • Android SDK at /Users/navaronbracke/Library/Android/sdk
    • Platform android-33, build-tools 33.0.0
    • ANDROID_HOME = /Users/navaronbracke/Library/Android/sdk
    • Java binary at: /Applications/Android
      Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build
      11.0.12+0-b1504.28-7817840)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 13.4.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • CocoaPods version 1.11.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.2)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build
      11.0.12+0-b1504.28-7817840)

[✓] VS Code (version 1.69.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.44.0

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-x64     • macOS 12.2.1 21D62 darwin-x64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 103.0.5060.134

[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!
Steps to reproduce
  1. Use store.box<T>().query(condition).watch() to create a Stream
  2. Setup a StreamSubscription for the stream
  3. Cancel the subscription
  4. The query never called its close() method (I can only speculate here)
Expected behavior

The underlying query should be disposed when the subscription is cancelled.

Code
  Stream<Query<T>> watch({bool triggerImmediately = false}) {
    final queriedEntities = HashSet<Type>();
    _fillQueriedEntities(queriedEntities);
    final query = build();
    late StreamSubscription<void> subscription;
    late StreamController<Query<T>> controller;
    final subscribe = () {
      subscription = _store.entityChanges.listen((List<Type> entityTypes) {
        if (entityTypes.any(queriedEntities.contains)) {
          controller.add(query);
        }
      });
    };
    controller = StreamController<Query<T>>(
        onListen: subscribe,
        onResume: subscribe,
        onPause: () => subscription.pause(),
        onCancel: () => subscription.cancel()); // The query should also be closed here?
    if (triggerImmediately) controller.add(query);
    return controller.stream;
  }

I'd expect to see

onCancel: (){
  subscription.cancel();
  query.close();
}
Logs, stack traces

N/A

Additional context

N/A

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Query.watch implementation included in the issue, focusing on the StreamController cancellation callback and the query created by build(). Reproduce the reported subscription-cancellation case, then verify that cancellation releases the underlying query and add regression coverage for that behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart, flutter
Domain
databases, mobile
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.