Skip to content
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

How can I implement the Lock/Unlock mechanism with version 5+ #2014

Closed
burekas7 opened this issue Oct 29, 2023 · 4 comments
Closed

How can I implement the Lock/Unlock mechanism with version 5+ #2014

burekas7 opened this issue Oct 29, 2023 · 4 comments
Labels
s: best practise It's the best way to do something so far

Comments

@burekas7
Copy link

burekas7 commented Oct 29, 2023

Request Statement

@cfa
I have a really significant use of the lock/unlock mechanism that was in the old versions (below 5.0.0),
mainly for use when the Internet connection disconnects and comes back, among other things.
For example with the use of the Queue package (but not only):
So requests are waiting to be sent until the connection returns, and meanwhile the Futures in the Queue are waiting and so is Queue.onComplete.

I looked for different Interceptors to meet this need and none perform the operation performed by the lock/unlock mechanism (which is of course based on the Lock class that was found in the interceptor.dart file)

I would like to know how I can implement this mechanism also in the new versions (5+)
or if it is still possible to return this mechanism?
(I didn't understand why it was removed in the first place)

Thanks in advance

@burekas7 burekas7 added the s: feature This issue indicates a feature request label Oct 29, 2023
@AlexV525 AlexV525 added e: documentation Improvements or additions to documentation p: dio Targeting `dio` package labels Oct 31, 2023
@AlexV525
Copy link
Member

AlexV525 commented Nov 9, 2023

Pseudo flow:

  1. Defines a global completer: Completer<void>? _connectionsLock
  2. If connections are unavailable, assign a Completer to the global.
  3. Implement a QueuedInterceptor with onRequest, and write await _connectionsLock?.future.
  4. If connections become available, resolve the lock and unassign it from the global.

@burekas7
Copy link
Author

burekas7 commented Nov 10, 2023

@AlexV525
Thanks a lot. It's working!!!
(Although I think it would be nice if it was built-in as it was before)

This is my implementation:

class NetworkManager with ChangeNotifier {

  final Connectivity _connectivity = Connectivity();
  late StreamSubscription _streamSubscription;
  ConnectivityResult connectivityResult = ConnectivityResult.none;
  
  final Dio _dio = Dio();
  late Completer<void>? _connectionLockCompleter = Completer<void>();
  
  NetworkManager() {
    setupQueuedInterceptorsLockWrapper();
  
    _streamSubscription = _connectivity.onConnectivityChanged.listen((connectivityResult) async {
      this.connectivityResult = connectivityResult;
      print("Connectivity status: ${this.connectivityResult.name}");
      if (connectivityResult != ConnectivityResult.none) {
        unlock();
      } else {
        lock();
      }
    });
  }
  
  void lock() {
    if (_connectionLockCompleter == null) {
      _connectionLockCompleter = Completer<void>();
    }
  }

  void unlock() {
    _connectionLockCompleter?.complete();
    _connectionLockCompleter = null;
  }
  
  void setupQueuedInterceptorsLockWrapper() {
    _dio.interceptors.add(QueuedInterceptorsWrapper(
        onRequest: (RequestOptions options, RequestInterceptorHandler handler) async {
      if (_connectionLockCompleter != null) {
        await _connectionLockCompleter!.future;
      }
      return handler.next(options);
    }));
  }
  
  @override
  void dispose() {
    _streamSubscription.cancel();
    super.dispose();
  }
}

@AlexV525
Copy link
Member

Some suggestions about your implementation:

  1. Do not use late for the lock, it's unnecessary.
  2. setupQueuedInterceptorsLockWrapper is unnecessary because you can write Dio()..interceptors.add(foo).
  3. if (_connectionLockCompleter != null) is unnecessary because you can write await _connectionLockCompleter?.future.

@AlexV525 AlexV525 closed this as not planned Won't fix, can't repro, duplicate, stale Nov 10, 2023
@AlexV525 AlexV525 added s: best practise It's the best way to do something so far and removed s: feature This issue indicates a feature request e: documentation Improvements or additions to documentation p: dio Targeting `dio` package labels Nov 10, 2023
@burekas7
Copy link
Author

burekas7 commented Nov 10, 2023

@AlexV525
Thanks for the suggestions.

Regarding (2), in my code I have flags to enable/disable interceptors, so I took it from there.
For this code here you are right.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
s: best practise It's the best way to do something so far
Projects
None yet
Development

No branches or pull requests

2 participants