A library to easily handle sequential queueing of futures in dart.

Last update: May 22, 2022

queue

Build Status

Easily queue futures and await their values.

This library allows you to send a future to central queue. The queue will execute the futures in the order they are queued and once the future is complete it will return its result.

My use case was to rate limit calls to bluetooth devices. There were multiple bluetooth devices connected that may have different commands being sent from lots of areas in the app. The devices were tripping over themselves and not responding. A stream wasn't the appropriate tool as I needed to get the result back. Hence a library was born.

Alternative use cases could be spidering a website, downloading a number of files, or rate limiting calls to an API.

🔥 🔥 🔥 Shameless plug! 🔥 🔥 🔥

Want to write server apps in dart like ExpressJS? Check out my new open source plugin Alfred https://pub.dev/packages/alfred

Usage

The most simple example:

import 'package:dart_queue/dart_queue.dart';

main() async {
  final queue = Queue();

  //Queue up a future and await its result
  final result = await queue.add(()=>Future.delayed(Duration(milliseconds: 10)));

  //Thats it!
}

A proof of concept:

import 'package:dart_queue/dart_queue.dart';

main() async {
  //Create the queue container
  final Queue queue = Queue(delay: Duration(milliseconds: 10));
  
  //Add items to the queue asyncroniously
  queue.add(()=>Future.delayed(Duration(milliseconds: 100)));
  queue.add(()=>Future.delayed(Duration(milliseconds: 10)));
  
  //Get a result from the future in line with await
  final result = await queue.add(() async {
    await Future.delayed(Duration(milliseconds: 1));
    return "Future Complete";
  });
  
  //100, 10, 1 will reslove in that order.
  result == "Future Complete"; //true
}

Parallel processing

This doesn't work in batches and will fire the next item as soon as as there is space in the queue Use [Queue(delayed: ...)] to specify a delay before firing the next item

import 'package:dart_queue/dart_queue.dart';

main() async {
  final queue = Queue(parallel: 2);

  //Queue up a future and await its result
  final result1 = await queue.add(()=>Future.delayed(Duration(milliseconds: 10)));
  final result2 = await queue.add(()=>Future.delayed(Duration(milliseconds: 10)));

  //Thats it!
}

On complete

import 'package:dart_queue/dart_queue.dart';

main() async {
  final queue = Queue(parallel: 2);

  //Queue up a couple of futures
  queue.add(()=>Future.delayed(Duration(milliseconds: 10)));
  queue.add(()=>Future.delayed(Duration(milliseconds: 10)));


  // Will only resolve when all the queue items have resolved.
  await queue.onComplete;
}

Rate limiting

You can specify a delay before the next item is fired as per the following example:

import 'package:dart_queue/dart_queue.dart';

main() async {
  final queue = Queue(delay: Duration(milliseconds: 500)); // Set the delay here

  //Queue up a future and await its result
  final result1 = await queue.add(()=>Future.delayed(Duration(milliseconds: 10)));
  final result2 = await queue.add(()=>Future.delayed(Duration(milliseconds: 10)));

  //Thats it!
}

Cancel

If you need to stop a queue from processing call Queue.cancel();

This will cancel the remaining items in the queue by throwing a QueueCancelledException. A cancelled queue is "dead" and should be recreated. If you try adding items to the queue after you call cancel, it will throw a QueueCancelledException.

If you have no reason to listen to the results of the items, simply call dispose.

If you want to wait until all the items which are inflight complete, call Queue.onComplete first.

Disposing

If you need to dispose of the queue object (best practice in flutter any any time the queue object will close) simply call queue.dispose();

This is necessary to close the Queue.remainingItems controller.

Reporting

If you want to query how many items are outstanding in the queue, listen to the Queue.remainingItems stream.

import 'package:dart_queue/dart_queue.dart';
final queue = Queue();

final remainingItemsStream = queue.remainingItems.listen((numberOfItems)=>print(numberOfItems));

//Queue up a couple of futures
queue.add(()=>Future.delayed(Duration(milliseconds: 10)));
queue.add(()=>Future.delayed(Duration(milliseconds: 10)));

// Will only resolve when all the queue items have resolved.
await queue.onComplete;
remainingItemsStream.close();
queue.dispose(); // Will clean up any resources in the queue if you are done with it.

Contributing

Pull requests are welcome. There is a shell script ci_checks.sh that will run the checks to get past CI and also format the code before committing. If that all passes your PR will likely be accepted.

Please write tests to cover your new feature.

GitHub

https://github.com/rknell/dart_queue
Comments
  • 1. Wait for all futures before disposing?

    Hi, thanks for this useful plugin!

    Would it be possible to add a way to wait on all futures before disposing? I'm using this to queue writes to a file, so it'd be quite helpful as it's important data that needs to be written.

    Reviewed by hacker1024 at 2020-10-12 12:56
  • 2. identifier to each queue so that the same algorithm is rerun while in process

    Hello, I am implementing this library with the video thumbnail, but I have a problem, which is that sometimes the same element is called 2 times, causing an unnecessary queue to be generated, so I would like for example:

    Reviewed by kevin4dhd at 2022-01-14 03:20
  • 3. Add generic types + hide implementation

    Hi,

    Thanks for creating this package, I find it very useful :) I edited your code a little, I thought I could make this PR.

    This PR:

    • Adds generic types. I think they're very necessary for type inference, particularly for the add method.
    • Hides the implementation. In particular, it makes private the following fields: nextCycle, isCancelled, isProcessing. Keeping them public could break the logic if they're modified. It also makes the process function private, I thought it would be better, what do you think?
    • Adds some documentation for public functions and fields.
    Reviewed by axel-op at 2020-05-12 21:47
  • 4. Queue.onComplete not return when queue is empty

    I used queue to wait for all requests finished like this:

    var queue = Queue(parallel: 4);
    for (final item in items) {
       if(valid(item)) {
            queue.add(() => _sendRequest(item));
       }
    }
    
    await queue.onComplete;
    print('completed');
    

    For some reasons, if there is no valid item in for loop, the queue is empty. And in this case it pauses at await queue.onComplete forever. Expect: it should allow to go through next line if queue is empty.

    Reviewed by ductranit at 2021-10-05 06:49
  • 5. Specify the maximum size

    In combination with #6, a way to limit the queue in size would be helpful as well.

    This may be trickier to achieve if items are added from both sides.

    Reviewed by ened at 2021-08-05 04:50
  • 6. Feature/priorities

    We needed the option to enqueue tasks with priorities. This is a first shot at it. Let me know what you think.

    • Also fixes obsolete imports in the README.

    First step towards https://github.com/rknell/dart_queue/issues/3


    And one question: Some tests were running very flaky on my machine, namely it should handle an error correctly (also testing oncomplete) fails from time to time with this error message:

    00:32 +5 -1: Queue it should handle an error correctly (also testing oncomplete) [E]                                                                             
      TimeoutException after 0:00:30.000000: Test timed out after 30 seconds. See https://pub.dev/packages/test#timeouts
      dart:isolate  _RawReceivePortImpl._handleMessage
    

    Any idea? I am on latest macOS 11.2.1 and this is my flutter doctor:

    [✓] Flutter (Channel stable, 2.0.1, on macOS 11.2.1 20D74 darwin-x64, locale en-GB)
    [✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
    [✓] Xcode - develop for iOS and macOS
    [✗] Chrome - develop for the web (Cannot find Chrome executable at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome)
        ! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.
    [✓] Android Studio (version 4.1)
    [✓] VS Code (version 1.54.1)
    [✓] Connected device (2 available)
    
    Reviewed by hffmnn at 2021-03-08 14:18
  • 7. Inserting item at a specific position in the queue

    If i for example have five items remaining in the queue is there any way to insert a new future into for example a second position? And thanks for the package, it's really useful!

    Reviewed by logic-and-math at 2020-12-07 18:25

Related

A most easily usable cookie management library in Dart. With SweetCookieJar, you can easily manage cookie on your application.
A most easily usable cookie management library in Dart. With SweetCookieJar, you can easily manage cookie on your application.

A most easily usable cookie management library in Dart! 1. About 1.1. Introduction 1.1.1. Install Library 1.1.2. Import It 1.1.3. Use SweetCookieJar 1

May 19, 2022
A most easily usable cache management library in Dart. With CacheStorage, you can easily manage cache on your application.

A most easily usable cache management library in Dart! 1. About 1.1. Introduction 1.1.1. Install Library 1.1.2. Import It 1.1.3. Use CacheStorage 1.2.

Dec 13, 2021
A most easily usable RESAS API wrapper in Dart. With this library, you can easily integrate your application with the RESAS API.

A most easily usable RESAS API wrapper library in Dart! 1. About 1.1. What Is RESAS? 1.2. Introduction 1.2.1. Install Library 1.2.2. Import It 1.2.3.

Apr 7, 2022
A Dart package to handle HTTP services

http_services A package to support the creation of Http services in a Dart application. Features convenient methods to perform HTTP requests disposing

Jul 27, 2021
A most easily usable Duolingo API wrapper in Dart. Duolingo4D is an open-sourced Dart library.

A most easily usable Duolingo API wrapper in Dart! 1. About Duolingo4D Duolingo4D is an open-sourced Dart library. With Duolingo4D, you can easily int

Mar 1, 2022
A package help you to make api call and handle error faster, also you can check for internet before call api.

http_solver ##not for production use, only for learning purpose. A package help you to make api call and handle error faster, also you can check for i

Jun 18, 2020
SearchBar widget to handle most of search cases

flappy_search_bar A SearchBar widget handling most of search cases. Usage To use this plugin, add flappy_search_bar as a dependency in your pubspec.ya

May 7, 2022
⚡ Cache Manager A tidy utility to handle cache of your flutter app like a Boss.

⚡ Cache Manager A tidy utility to handle cache of your flutter app like a Boss. It provides support for both iOS and Android platforms (offcourse). ??

Jan 8, 2022
AuthorizationHeader is an open-sourced Dart library. With AuthorizationHeader, you can easily manage authorization header on your application.

A most easily usable authorization header management library in Dart! 1. About 1.1. Supported 1.1.1. Authorization Header 1.1.2. Authorization Type 1.

Dec 24, 2021
A library for building REST APIs easily with Dart

A library for building REST APIs easily with Dart modeled after Express JS for Node Js. The library is still a work in progress and open to contributi

Apr 3, 2022
A most easily usable JSON wrapper library in Dart

A most easily usable JSON response wrapper library in Dart! 1. About 1.1. Introd

Jan 4, 2022
A most easily usable improvement rate calculator library in Dart.

A most easily usable improvement rate calculator library in Dart. With ImprovementRate, you can easily calculate improvement rate on your application.

Dec 27, 2021
A UI library for easily adding audio waveforms to your apps, with several customization options
A UI library for easily adding audio waveforms to your apps, with several customization options

A UI library for easily adding audio waveforms to your apps, with several custom

May 11, 2022
🚀 Simple library to download files easily.

Dart DL Simple library to download files easily. Links GitHub Pub.dev Documentation Features Uses native dart:io to get data. Ability to parse differe

Feb 11, 2022
Toast Library for Flutter, Easily create toast messages in single line of code
Toast Library for Flutter, Easily create toast messages in single line of code

Create Toast messages on a Flutter Event. fluttertoast: ^8.0.8 Toast Library for Flutter, Easily create Personalised toast messages in single line of

Feb 14, 2022
A middleware library for Dart's http library.

http_middleware A middleware library for Dart http library. Getting Started http_middleware is a module that lets you build middleware for Dart's http

Oct 23, 2021
Create dart data classes easily, fast and without writing boilerplate or running code generation.
Create dart data classes easily, fast and without writing boilerplate or running code generation.

Dart Data Class Generator Create dart data classes easily, fast and without writing boilerplate or running code generation. Features The generator can

Feb 28, 2022
Easily build and deploy your Dart web app to GitHub pages

Run flutter build web or dart pub run build_runner build and put the output in another branch. An easy way to update gh-pages. Install $ dart pub glob

Apr 18, 2022