Git Product home page Git Product logo

d-markey / squadron Goto Github PK

View Code? Open in Web Editor NEW
79.0 79.0 0.0 39.17 MB

Multithreading and worker thread pool for Dart / Flutter, to offload CPU-bound and heavy I/O tasks to Isolate or Web Worker threads.

Home Page: https://pub.dev/packages/squadron

License: MIT License

Dart 24.32% HTML 0.37% CSS 0.05% Batchfile 0.28% Smarty 0.12% Shell 0.20% JavaScript 74.66%
dart isolate parallelism-library thread webworker

squadron's People

Contributors

d-markey avatar dependabot[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

squadron's Issues

WorkerException: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'SendPort?'

Trying my first run converting a complex system to use isolates/workers, i get the exception in the title.

flutter: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'SendPort?'
flutter: #0      openChannel (package:squadron/src/native/channel.dart:103:11)
<asynchronous suspension>
d-markey/squadron_sample#1      Worker.send (package:squadron/src/worker.dart:107:9)
<asynchronous suspension>
d-markey/squadron#3      WorkerTask._runFuture (package:squadron/src/worker_task.dart:148:21)
<asynchronous suspension>

I replicated the thumbnail example as far as I can tell.

Here's my code:

solver_service.dart

import 'dart:async';

import 'package:squadron/squadron.dart';

import '../position_manager_thread.dart';

abstract class SolverService {
  FutureOr<Map<String, dynamic>> initRoot(Map<String, dynamic> rootNodeJson);

  FutureOr<Map<String, dynamic>> performLayout(
    Set<Map<String, dynamic>> nodesReference,
    Set<String> createdNodes,
    Set<String> removedNodes,
    Set<String> adoptedNodes,
    Set<String> droppedNodes,
    Set<String> changedNodes,
  );

  static const cmdPerformLayout = 1;
  static const cmdInitRoot = 2;
}

class SolverServiceImpl implements SolverService, WorkerService {
  final PositionManagerThread positionManager =
      PositionManagerThread(notifier: (pos) => print(pos));

  @override
  FutureOr<Map<String, dynamic>> initRoot(Map<String, dynamic> rootNodeJson) =>
      positionManager.initRoot(rootNodeJson).toJson();

  @override
  FutureOr<Map<String, dynamic>> performLayout(
    Set<Map<String, dynamic>> nodesReference,
    Set<String> createdNodes,
    Set<String> removedNodes,
    Set<String> adoptedNodes,
    Set<String> droppedNodes,
    Set<String> changedNodes,
  ) async {
    return positionManager
        .performLayout(
          nodesReference,
          createdNodes,
          removedNodes,
          adoptedNodes,
          droppedNodes,
          changedNodes,
        )
        .toJson();
  }

  @override
  late final Map<int, CommandHandler> operations = {
    SolverService.cmdPerformLayout: (WorkerRequest r) => performLayout(
          r.args[0],
          r.args[1],
          r.args[2],
          r.args[3],
          r.args[4],
          r.args[5],
        ),
    SolverService.cmdInitRoot: (WorkerRequest r) => initRoot(
          r.args[0],
        ),
  };
}

solver_worker_activator.dart:

// stub file, the file used at runtime will depend on the target platform
//   * cf "browser\solver_worker_activator.dart" for Web workers (browser platform)
//   * cf "vm\solver_worker_activator.dart" for Isolate workers (vm platform)

// of course, if your application does not target both Web and VM platforms,
// you need not define a stub file and can go directly for your target platform

import 'solver_worker_pool.dart' show SolverWorker;

SolverWorker createWorker() =>
    throw UnsupportedError('Not supported on this platform');

solver_worker_pool:

// this is a helper file to expose Squadron workers and worker pools as a SolverService

import 'dart:async';

import 'package:codelessly_flutter/managers/position_manager/multithreading/solver_service.dart';
import 'package:squadron/squadron.dart';

// this is where the stub file comes into action
//
// of course, if your application does not target both Web and VM platforms,
// you need not define a stub file and can go directly for your target platform
import 'solver_worker_activator.dart'
    if (dart.library.js) 'package:codelessly_flutter/managers/position_manager/multithreading/browser/solver_worker_activator.dart'
    if (dart.library.html) 'package:codelessly_flutter/managers/position_manager/multithreading/browser/solver_worker_activator.dart'
    if (dart.library.io) 'package:codelessly_flutter/managers/position_manager/multithreading/vm/solver_worker_activator.dart';

// Implementation of SolverService as a Squadron worker pool
class SolverWorkerPool extends WorkerPool<SolverWorker>
    implements SolverService {
  SolverWorkerPool(ConcurrencySettings concurrencySettings)
      : super(createWorker, concurrencySettings: concurrencySettings);

  @override
  FutureOr<Map<String, dynamic>> initRoot(Map<String, dynamic> rootNodeJson) =>
      execute((w) async => w.initRoot(rootNodeJson));

  @override
  FutureOr<Map<String, dynamic>> performLayout(
    Set<Map<String, dynamic>> nodes,
    Set<String> createdNodes,
    Set<String> removedNodes,
    Set<String> adoptedNodes,
    Set<String> droppedNodes,
    Set<String> changedNodes,
  ) =>
      execute((w) async => w.performLayout(
            nodes,
            createdNodes,
            removedNodes,
            adoptedNodes,
            droppedNodes,
            changedNodes,
          ));
}

// Implementation of SolverService as a Squadron worker
class SolverWorker extends Worker implements SolverService {
  SolverWorker(dynamic entryPoint, {String? id, List args = const []})
      : super(entryPoint, id: id, args: args);

  @override
  FutureOr<Map<String, dynamic>> initRoot(Map<String, dynamic> rootNodeJson) {
    return send(
      SolverService.cmdInitRoot,
      [
        rootNodeJson,
      ],
    );
  }

  @override
  FutureOr<Map<String, dynamic>> performLayout(
    Set<Map<String, dynamic>> nodes,
    Set<String> createdNodes,
    Set<String> removedNodes,
    Set<String> adoptedNodes,
    Set<String> droppedNodes,
    Set<String> changedNodes,
  ) {
    return send(
      SolverService.cmdPerformLayout,
      [
        nodes,
        createdNodes,
        removedNodes,
        adoptedNodes,
        droppedNodes,
        changedNodes,
      ],
    );
  }
}

solver_vm.dart:

// Isolate implementation (VM patform)

import 'package:squadron/squadron_service.dart';

import '../solver_service.dart';

void start(Map command) => run((startRequest) => SolverServiceImpl(), command);

solver_worker_activator.dart:

// Creation of the Isolate

import '../solver_worker_pool.dart' show SolverWorker;
import 'solver_worker.dart' as isolate;

SolverWorker createWorker() => SolverWorker(isolate.start);

Usage is quite simple:

  // Crashes if maxParallel is set to 1 for some reason. I only want one instance of this worker/isolate at all times through the life cycle of the app
  final SolverWorkerPool pool = SolverWorkerPool(
      const ConcurrencySettings(minWorkers: 1, maxWorkers: 1, maxParallel: 2));

  Future<void> initRoot(RootNode node) async {
    final LayoutResult result =
        LayoutResult.fromJson(await pool.initRoot(node.toJson()));

I'm not really sure what I'm doing wrong. There's no mention or example that brings up SendPort/ReceiverPort for Squadron.
I get this error for the performLayout() function as well.

I'm running this in a MacOS window. So the isolate only. No javascript

Fix the dart to js parser code on the readme.md

On the section Releasing Your App on the README.md file, the command to parse a dart file to Javascript is not accurate.
It shows:
dart compile js -o lib/src/browser/service_worker.dart web/service_worker.dart.js

But it should be like this:
dart compile js lib/src/browser/service_worker.dart -o web/service_worker.dart.js

The -o indicates the path to the compiled js file, right?

Edit: I just saw that i'm in the samples repo, but the issue is still valid, not for this repo, but for the package one.

Decoding JSON to generic class

Hey, I am trying to parse JSON string to dart object using Model.fromJson method inside a squadron worker.

This should work fine for a given model class (not tested though).

@freezed
class Model with _$Model {
  const factory Model({
    required final int id,
    required final String name,
  }) = _Model;
  factory Model.fromJson(final Map<String, dynamic> json) =>
      _$ModelFromJson(json);
}

@SquadronService()
class MyService {
  @SquadronMethod()
  FutureOr<Model> loadModel(final String data) {
    final json = jsonDecode(data) as Map<String, Object?>;
    return Model.fromJson(json);
  }
}

But what I want to do is parse the JSON string to a generic dart object with something as:

@SquadronService()
class MyService {
  @SquadronMethod()
  FutureOr<T> load({
     required final String data,
     required final T Function(Map<String, Object?>) fromJson,
   } ) {
    final json = jsonDecode(data) as Map<String, Object?>;
    return fromJson(json);
  }
}

Here, I can't pass fromJson method as an argument. It doesn't let the build runner pass with squadron_builder. Previously when I was using dart:isolate, I was able to pass this using SendPort.

My use-case is more complicated than this, but I am stuck by this issue. One way to solve this is by returning the Map<String, Object?> and use fromJson from main thread. However, since I am offloading my task, I wanted to parse the Json to dart object from the worker thread.

Can't get web worker going (native working fine)

Hi - I'm just starting to learn/use squadron (thanks for doing this BTW)...

What I've tried to do (as part of learning) is to take the sample code in the readme file and combine that into a test app to make sure I understand all the parts. I did find the other sample (squadron_sample) to be too complicated to start with. My goal was to create a bit of a "hello world".

My end goal is to take a parser I've got (it parses VCD [Value Change Dump] files that can get quite large (hundreds of MB)).

Here's a link to my repo "Hello World": squadron_test

I'm able to get this to work on the Mac, with the web version, I get Exceptions but I can't isolate where they would be coming from.

The main.dart just puts a button widget at the center. Click on that and the _onPressed function runs the code you have the section of the readme: "you can now distribute your workloads". Of course, I'm just using the debug window for now.

I setup all the worker/service stuff in the sample folder and made the folder structure look like the squadron_sample. The only thing I changed from the readme file code is the addition of some print statements. The readme file also still uses deprecated stuff (maxWorkers/maxParallel) so I changed that to use ConcurrencySettings.

In the root/lib folder there's two files to generate the .js files, one is build_web_worker_posix and the other is build_web_worker_windows.bat. I'm using a Mac for development, and I think you're using Windows, so that should let you do your own dart2js compile. I didn't try this on Windows (just Mac and web). If you want me to do Windows or Linux or mobile, I can do that as well. I did put the <script> in index.html as well.

I'm guessing that I'm missing something pretty basic in my "hello world". So, I'm hoping you can quickly find what's wrong. Maybe some of this would be useful to you as well. I don't want to move on to getting my parser in there until I can get this basic test going.

I can get you a full Flutter doctor if you want, but hopefully, this will do: Flutter (Channel stable, 2.10.4, on macOS 12.3.1 21E258 darwin-arm, locale en-US)

Thanks for you help on this, I really appreciate it.
Martin

WASM Support

Hey @d-markey . Would be great to update squadron to the new dart:js_interop since flutter 3.22.0 added stable wasm support (which doesn't work with dart:html and js/js).

error when using `JsonSerializable` on web

recently, I stuck with a problem on the web. below is an error.

error: ["$W","TypeError: Instance of 'minified:z<dynamic>': type 'minified:z<dynamic>' is not a subtype of type 'List<double>'","TypeError: Instance of 'minified:z<dynamic>': type 'minified:z<dynamic>' is not a subtype of type 'List<double>'\n    at Object.b (http://localhost:62206/workers/neverland_worker.dart.js:282:3)\n    at Object.i4 (http://localhost:62206/work...

I figure out that the error comes from type casting on .g.dart, it changes from weak type (important, JS doesn't have a generic type) to strict type like List<double>.

size: const SizeConverter().fromJson(json['size'] as List<double>),

so, when you have an object containing other objects and want to encode the object on the Worker class and decode it on the Service class using code generated by JsonSerializable, change the type to dynamic.

below is an example.

class SizeConverter implements JsonConverter<Size, List<double>> {

  const SizeConverter();

  @override
  Size fromJson(List<double> json) {
    return Size(json[0], json[1]);
  }

  @override
  List<double> toJson(Size object) {
    return [object.width, object.height];
  }
}

on the Web, there isn't a type like List<double>, only List; so change like this.

class SizeConverter implements JsonConverter<Size, dynamic> {

  const SizeConverter();

  @override
  Size fromJson(dynamic json) {
    return Size(json[0], json[1]);
  }

  @override
  dynamic toJson(Size object) {
    return [object.width, object.height];
  }
}

I know that README also says you should take care when using JsonSerializable, but I want to show another case.

Uncaught Error: Expected a value of type 'FutureOr<Map<String, dynamic>>?', but got one of type 'LinkedMap<dynamic, dynamic>

Hi @d-markey, I think I have found a bug, it just happens on web. I want to return a Map<String, dynamic> but It seems I can't. Given this code,

class ComputeService implements WorkerService {
  Future<Map<String, dynamic>> whateverFnc() async {
    final Map<String, dynamic> res = {
      'num': 24,
    };
    return res;
  }

  static const whateverFncCommand = 1;

  @override
  Map<int, CommandHandler> get operations {
    return {
      whateverFncCommand: (WorkerRequest r) {
        return whateverFnc();
      }
    };
  }
}


class ComputeWorkerPool extends WorkerPool<ComputeWorker> implements ComputeService {
  ComputeWorkerPool(ConcurrencySettings concurrencySettings)
      : super(
          createWorker,
          concurrencySettings: concurrencySettings,
        );

  @override
  Future<Map<String, dynamic>> whateverFnc() => execute((w) => w.whateverFnc());
}

class ComputeWorker extends Worker implements ComputeService {
  ComputeWorker(dynamic entryPoint, {String? id, List args = const []}) : super(entryPoint, id: id, args: args);

  @override
  Future<Map<String, dynamic>> whateverFnc() {
    return send(ComputeService.whateverFncCommand, []);
  }
}

Uncaught Error: Expected a value of type 'FutureOr<Map<String, dynamic>>?', but got one of type 'LinkedMap<dynamic, dynamic>' at Object.throw_ [as throw] (errors.dart:251:49) at Object.castError (errors.dart:84:3) at Object.cast [as as] (operations.dart:452:10) at dart.NullableType.new.as (types.dart:367:9) at channel.dart:62:18 at Object._checkAndCall (operations.dart:334:14) at Object.dcall (operations.dart:339:39) at MessagePort.<anonymous> (html_dart2js.dart:37230:58)

If I return String or number it works great.

Thanks for your work,

Listen to task started/completed events

Is there any similar api to workerPool.registerWorkerPoolListener((worker, removed) {}); that can listen to task being started or completed? I didn't find one.

Is it possible to make http-request with Squadron?

Hi!

I have studied the documentation and example, but I'm still not certain how can I create an http-request with Squadron? If it's possible.

I have a post-request, which is uploading some file. And I want to perform it in an isolated worker (on web). And also I need to listen to the upload progress somehow.

Is that possible? And how can I do that?

WorkerException: TypeError: Instance of 'JsLinkedHashMap<dynamic, dynamic>': type 'JsLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, dynamic>'

The issues just don't stop do they?

So how do we fix this one?

WorkerException: TypeError: Instance of 'JsLinkedHashMap<dynamic, dynamic>': type 'JsLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, dynamic>'
TypeError: Instance of 'JsLinkedHashMap<dynamic, dynamic>': type 'JsLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, dynamic>'
    at Object.wrapException (http://localhost:5000/solver_worker.dart.js:762:17)
    at Object._failedAsCheck (http://localhost:5000/solver_worker.dart.js:1931:15)
    at Rti._generalAsCheckImplementation [as _as] (http://localhost:5000/solver_worker.dart.js:1920:9)
    at Object.LinkedHashSet_LinkedHashSet$from (http://localhost:5000/solver_worker.dart.js:3775:28)
    at PositionManagerThread.performLayout$6 (http://localhost:5000/solver_worker.dart.js:16322:28)
    at SolverServiceImpl_operations_closure.call$1 (http://localhost:5000/solver_worker.dart.js:16141:64)
    at http://localhost:5000/solver_worker.dart.js:8415:27
    at _wrapJsFunctionForAsync_closure.$protected (http://localhost:5000/solver_worker.dart.js:3111:15)
    at _wrapJsFunctionForAsync_closure.call$2 (http://localhost:5000/solver_worker.dart.js:10874:12)
    at Object._asyncStartSync (http://localhost:5000/solver_worker.dart.js:3075:20)
solver_worker.dart.js 762:17                                                  wrapException
solver_worker.dart.js 1931:15                                                 _failedAsCheck
solver_worker.dart.js 1920:9                                                  _generalAsCheckImplementation
solver_worker.dart.js 3775:28                                                 LinkedHashSet_LinkedHashSet$from
solver_worker.dart.js 16322:28                                                performLayout$6
solver_worker.dart.js 16141:64                                                call$1
solver_worker.dart.js 8415:27                                                 <fn>
solver_worker.dart.js 3111:15                                                 $protected
solver_worker.dart.js 10874:12                                                call$2
solver_worker.dart.js 3075:20                                                 _asyncStartSync
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 251:49  throw_
packages/squadron/src/worker.dart 134:7                                       send
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 60:31            <fn>
dart-sdk/lib/async/zone.dart 1450:47                                          _rootRunBinary
dart-sdk/lib/async/zone.dart 1342:19                                          runBinary
dart-sdk/lib/async/future_impl.dart 174:22                                    handleError
dart-sdk/lib/async/future_impl.dart 778:46                                    handleError
dart-sdk/lib/async/future_impl.dart 799:13                                    _propagateToListeners
dart-sdk/lib/async/future_impl.dart 609:5                                     [_completeError]
dart-sdk/lib/async/future_impl.dart 665:7                                     <fn>
dart-sdk/lib/async/zone.dart 1426:13                                          _rootRun
dart-sdk/lib/async/zone.dart 1328:19                                          run
dart-sdk/lib/async/zone.dart 1236:7                                           runGuarded
dart-sdk/lib/async/zone.dart 1276:23                                          callback
dart-sdk/lib/async/schedule_microtask.dart 40:11                              _microtaskLoop
dart-sdk/lib/async/schedule_microtask.dart 49:5                               _startMicrotaskLoop
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 166:15           <fn>

For reference, this is what the performLayout function does:
image

and the solver impl is unchanged

image

One theory is that .toJson() is creating a Map<String, dynamic> and js/dart simply don't know how to strip its type to a Map, so I tried to convert map using your function:

image

Unfortunately, this does not resolve the issue. It's the same error

WorkerException: TypeError: Instance of 'JsLinkedHashMap<dynamic, dynamic>': type 'JsLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, dynamic>'
TypeError: Instance of 'JsLinkedHashMap<dynamic, dynamic>': type 'JsLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, dynamic>'

And looking at the js stacktrace and the generated js file, It seems it is throwing at this line:

image

Which is the equivalent of this:

image

The desired type is

    Set<Map<String, dynamic>> nodeReferences,

v4.3.7 depends on meta: ^1.9.1 which is incompatible with fluter_test from Flutter 3.7.12

Hey! ๐Ÿ‘‹

I love this package, however, due to the latest version v4.3.7 depending on meta: ^1.9.1 I can't use it with Flutter 3.7.12

When trying to upgrade I get an error:

Because every version of flutter_test from sdk depends on meta 1.8.0 and squadron >=4.3.7 depends on meta ^1.9.1, flutter_test from sdk is incompatible with squadron >=4.3.7.
So, because test_app depends on both squadron ^4.3.7 and flutter_test from sdk, version solving failed.

Is there any specific reason you bumped the requirement to meta: ^1.9.1? I've seen that in v4.3.6 4123d9c you downgraded it back to meta: ^1.8.0

Error: [-2, lib/.... ] Refused to execute script

Bit of an issue using squadron and squadron build.

Summary: Generated Code will not load, when worker.start() is called, the following error is produced.

Refused to execute script from 'http://localhost:57183/lib/service/live feed/live feed.web.g.dart.js' because its MIME type ('text/html') is not executable, localhost/:1
and strict MIME type checking is enabled.

followed by:

Uncaught (in promise) Error: [-2, "lib/service/live_feed/live_feed.web.g.dart.js: error / [object Event]", "dart-
errors.dart:321
sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 942:28
get current\npackages/squadron/src/worker_exception.dart 17:34
new\packages/squadron/src/browser/_channel.dart 273:21
367:37
<fn>\ndart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
_checkAndCall\ndart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart372:39
dcall\ndart-sdk/lib/html/dart2js/html_dart2js.dart 37236:58
<fn>\n", null, null]
dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 942:28
get current
packages/squadron/src/worker exception.dart 17:34
new
packages/squadron/src/browser/_channel.dart 273:21
<fn>
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 367:37 checkAndCall dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 372:39 dcall dart-sdk/lib/html/dart2js/html dart2js.dart 37236:58
Flutter Environment & Dependencies
[โœ“] Flutter (Channel stable, 3.10.6, on macOS 13.5 22G74 darwin-x64, locale en-AU)
    โ€ข Flutter version 3.10.6 on channel stable at /Users/rayk/development/flutter
    โ€ข Upstream repository https://github.com/flutter/flutter.git
    โ€ข Framework revision f468f3366c (3 weeks ago), 2023-07-12 15:19:05 -0700
    โ€ข Engine revision cdbeda788a
    โ€ข Dart version 3.0.6
    โ€ข DevTools version 2.23.1

[โœ“] Android toolchain - develop for Android devices (Android SDK version 33.0.1)
    โ€ข Android SDK at /Users/rayk/Library/Android/sdk
    โ€ข Platform android-33, build-tools 33.0.1
    โ€ข Java binary at: /Users/rayk/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/223.8836.35.2231.10406996/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    โ€ข Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)
    โ€ข All Android licenses accepted.

[โœ“] Xcode - develop for iOS and macOS (Xcode 14.3.1)
    โ€ข Xcode at /Applications/Xcode.app/Contents/Developer
    โ€ข Build 14E300c
    โ€ข CocoaPods version 1.12.1

[โœ“] Chrome - develop for the web
    โ€ข Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[โœ“] IntelliJ IDEA Ultimate Edition (version 2023.2)
    โ€ข IntelliJ at /Users/rayk/Applications/JetBrains Toolbox/IntelliJ IDEA Ultimate.app
    โ€ข Flutter plugin version 75.0.4
    โ€ข Dart plugin version 232.8660.129

[โœ“] Connected device (2 available)
    โ€ข macOS (desktop) โ€ข macos  โ€ข darwin-x64     โ€ข macOS 13.5 22G74 darwin-x64
    โ€ข Chrome (web)    โ€ข chrome โ€ข web-javascript โ€ข Google Chrome 115.0.5790.114

[โœ“] Network resources
    โ€ข All expected network resources are available.

โ€ข No issues found!
Project Dependencies
packages:
  _fe_analyzer_shared:
    dependency: transitive
    description:
      name: _fe_analyzer_shared
      sha256: "405666cd3cf0ee0a48d21ec67e65406aad2c726d9fa58840d3375e7bdcd32a07"
      url: "https://pub.dev"
    source: hosted
    version: "60.0.0"
  analyzer:
    dependency: transitive
    description:
      name: analyzer
      sha256: "1952250bd005bacb895a01bf1b4dc00e3ba1c526cf47dca54dfe24979c65f5b3"
      url: "https://pub.dev"
    source: hosted
    version: "5.12.0"
  analyzer_plugin:
    dependency: transitive
    description:
      name: analyzer_plugin
      sha256: c1d5f167683de03d5ab6c3b53fc9aeefc5d59476e7810ba7bbddff50c6f4392d
      url: "https://pub.dev"
    source: hosted
    version: "0.11.2"
  archive:
    dependency: transitive
    description:
      name: archive
      sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a"
      url: "https://pub.dev"
    source: hosted
    version: "3.3.7"
  args:
    dependency: transitive
    description:
      name: args
      sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
      url: "https://pub.dev"
    source: hosted
    version: "2.4.2"
  async:
    dependency: transitive
    description:
      name: async
      sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
      url: "https://pub.dev"
    source: hosted
    version: "2.11.0"
  boolean_selector:
    dependency: transitive
    description:
      name: boolean_selector
      sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
      url: "https://pub.dev"
    source: hosted
    version: "2.1.1"
  build:
    dependency: transitive
    description:
      name: build
      sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
      url: "https://pub.dev"
    source: hosted
    version: "2.4.1"
  build_config:
    dependency: transitive
    description:
      name: build_config
      sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1
      url: "https://pub.dev"
    source: hosted
    version: "1.1.1"
  build_daemon:
    dependency: transitive
    description:
      name: build_daemon
      sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65"
      url: "https://pub.dev"
    source: hosted
    version: "4.0.0"
  build_resolvers:
    dependency: transitive
    description:
      name: build_resolvers
      sha256: "6c4dd11d05d056e76320b828a1db0fc01ccd376922526f8e9d6c796a5adbac20"
      url: "https://pub.dev"
    source: hosted
    version: "2.2.1"
  build_runner:
    dependency: "direct dev"
    description:
      name: build_runner
      sha256: "10c6bcdbf9d049a0b666702cf1cee4ddfdc38f02a19d35ae392863b47519848b"
      url: "https://pub.dev"
    source: hosted
    version: "2.4.6"
  build_runner_core:
    dependency: transitive
    description:
      name: build_runner_core
      sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41"
      url: "https://pub.dev"
    source: hosted
    version: "7.2.10"
  built_collection:
    dependency: "direct main"
    description:
      name: built_collection
      sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
      url: "https://pub.dev"
    source: hosted
    version: "5.1.1"
  built_value:
    dependency: "direct main"
    description:
      name: built_value
      sha256: "598a2a682e2a7a90f08ba39c0aaa9374c5112340f0a2e275f61b59389543d166"
      url: "https://pub.dev"
    source: hosted
    version: "8.6.1"
  built_value_generator:
    dependency: "direct dev"
    description:
      name: built_value_generator
      sha256: "14835d3ee2a0b19ffb263c57d82a3b2a64b0090d6b9d12e3b1646c1ff82a2476"
      url: "https://pub.dev"
    source: hosted
    version: "8.6.1"
  characters:
    dependency: transitive
    description:
      name: characters
      sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
      url: "https://pub.dev"
    source: hosted
    version: "1.3.0"
  chart_sparkline:
    dependency: "direct main"
    description:
      name: chart_sparkline
      sha256: "10c68b0062056471bd64afccb13cb5bcad6edc087b4f939991094bc68af4d673"
      url: "https://pub.dev"
    source: hosted
    version: "1.0.13"
  checked_yaml:
    dependency: transitive
    description:
      name: checked_yaml
      sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
      url: "https://pub.dev"
    source: hosted
    version: "2.0.3"
  ci:
    dependency: transitive
    description:
      name: ci
      sha256: "145d095ce05cddac4d797a158bc4cf3b6016d1fe63d8c3d2fbd7212590adca13"
      url: "https://pub.dev"
    source: hosted
    version: "0.1.0"
  cli_util:
    dependency: transitive
    description:
      name: cli_util
      sha256: b8db3080e59b2503ca9e7922c3df2072cf13992354d5e944074ffa836fba43b7
      url: "https://pub.dev"
    source: hosted
    version: "0.4.0"
  clock:
    dependency: transitive
    description:
      name: clock
      sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
      url: "https://pub.dev"
    source: hosted
    version: "1.1.1"
  code_builder:
    dependency: transitive
    description:
      name: code_builder
      sha256: "4ad01d6e56db961d29661561effde45e519939fdaeb46c351275b182eac70189"
      url: "https://pub.dev"
    source: hosted
    version: "4.5.0"
  collection:
    dependency: transitive
    description:
      name: collection
      sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
      url: "https://pub.dev"
    source: hosted
    version: "1.17.1"
  convert:
    dependency: transitive
    description:
      name: convert
      sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
      url: "https://pub.dev"
    source: hosted
    version: "3.1.1"
  crypto:
    dependency: transitive
    description:
      name: crypto
      sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
      url: "https://pub.dev"
    source: hosted
    version: "3.0.3"
  cupertino_icons:
    dependency: "direct main"
    description:
      name: cupertino_icons
      sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be
      url: "https://pub.dev"
    source: hosted
    version: "1.0.5"
  custom_lint:
    dependency: "direct dev"
    description:
      name: custom_lint
      sha256: "3ce36c04d30c60cde295588c6185b3f9800e6c18f6670a7ffdb3d5eab39bb942"
      url: "https://pub.dev"
    source: hosted
    version: "0.4.0"
  custom_lint_builder:
    dependency: transitive

    description:
      name: custom_lint_builder
      sha256: "73d09c9848e9f6d5c3e0a1809eac841a8d7ea123d0849feefa040e1ad60b6d06"
      url: "https://pub.dev"
    source: hosted
    version: "0.4.0"
  custom_lint_core:
    dependency: transitive
    description:
      name: custom_lint_core
      sha256: "9170d9db2daf774aa2251a3bc98e4ba903c7702ab07aa438bc83bd3c9a0de57f"
      url: "https://pub.dev"
    source: hosted
    version: "0.4.0"
  dart_style:
    dependency: transitive
    description:
      name: dart_style
      sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55"
      url: "https://pub.dev"
    source: hosted
    version: "2.3.2"
  equatable:
    dependency: "direct main"
    description:
      name: equatable
      sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
      url: "https://pub.dev"
    source: hosted
    version: "2.0.5"
  fake_async:
    dependency: transitive
    description:
      name: fake_async
      sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
      url: "https://pub.dev"
    source: hosted
    version: "1.3.1"
  faker:
    dependency: "direct main"
    description:
      name: faker
      sha256: "746e59f91d8b06a389e74cf76e909a05ed69c12691768e2f93557fdf29200fd0"
      url: "https://pub.dev"
    source: hosted
    version: "2.1.0"
  fast_immutable_collections:
    dependency: "direct main"
    description:
      name: fast_immutable_collections
      sha256: b4f7d3af6e90a80cf7a3dddd0de3b4a46acb446320795b77b034535c4d267fbe
      url: "https://pub.dev"
    source: hosted
    version: "9.1.5"
  ffi:
    dependency: transitive
    description:
      name: ffi
      sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99
      url: "https://pub.dev"
    source: hosted
    version: "2.0.2"
  file:
    dependency: transitive
    description:
      name: file
      sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
      url: "https://pub.dev"
    source: hosted
    version: "7.0.0"
  fixnum:
    dependency: transitive
    description:
      name: fixnum
      sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1"
      url: "https://pub.dev"
    source: hosted
    version: "1.1.0"
  fl_chart:
    dependency: "direct main"
    description:
      name: fl_chart
      sha256: c1e26c7e48496be85104c16c040950b0436674cdf0737f3f6e95511b2529b592
      url: "https://pub.dev"
    source: hosted
    version: "0.63.0"
  flex_color_scheme:
    dependency: "direct main"
    description:
      name: flex_color_scheme
      sha256: "659cf59bd5ccaa1e7de9384342be8b666ff10b108ed57a7fd46c122fb8bf6aca"
      url: "https://pub.dev"
    source: hosted
    version: "7.2.0"
  flex_seed_scheme:
    dependency: transitive
    description:
      name: flex_seed_scheme
      sha256: "29c12aba221eb8a368a119685371381f8035011d18de5ba277ad11d7dfb8657f"
      url: "https://pub.dev"
    source: hosted
    version: "1.4.0"
  flutter:
    dependency: "direct main"
    description: flutter
    source: sdk
    version: "0.0.0"
  flutter_hooks:
    dependency: "direct main"
    description:
      name: flutter_hooks
      sha256: b10cab7e0e4dbb60ff5360a740def3919aecbc672240f742a7130a2874204229
      url: "https://pub.dev"
    source: hosted
    version: "0.19.0"
  flutter_lints:
    dependency: "direct dev"
    description:
      name: flutter_lints
      sha256: "2118df84ef0c3ca93f96123a616ae8540879991b8b57af2f81b76a7ada49b2a4"
      url: "https://pub.dev"
    source: hosted
    version: "2.0.2"
  flutter_localizations:
    dependency: "direct main"
    description: flutter
    source: sdk
    version: "0.0.0"
  flutter_riverpod:
    dependency: "direct main"
    description:
      name: flutter_riverpod
      sha256: b83ac5827baadefd331ea1d85110f34645827ea234ccabf53a655f41901a9bf4
      url: "https://pub.dev"
    source: hosted
    version: "2.3.6"
  flutter_test:
    dependency: "direct dev"
    description: flutter
    source: sdk
    version: "0.0.0"
  fpdart:
    dependency: "direct main"
    description:
      name: fpdart
      sha256: "4a0d047c3359a4bdd19e4941603bbe394bd133b3772a38049e17f9534d47106e"
      url: "https://pub.dev"
    source: hosted
    version: "0.6.0"
  freezed:
    dependency: "direct main"
    description:
      name: freezed
      sha256: "2df89855fe181baae3b6d714dc3c4317acf4fccd495a6f36e5e00f24144c6c3b"
      url: "https://pub.dev"
    source: hosted
    version: "2.4.1"
  freezed_annotation:
    dependency: "direct main"
    description:
      name: freezed_annotation
      sha256: c3fd9336eb55a38cc1bbd79ab17573113a8deccd0ecbbf926cca3c62803b5c2d
      url: "https://pub.dev"
    source: hosted
    version: "2.4.1"
  frontend_server_client:
    dependency: transitive
    description:
      name: frontend_server_client
      sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612"
      url: "https://pub.dev"
    source: hosted
    version: "3.2.0"
  glob:
    dependency: transitive
    description:
      name: glob
      sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
      url: "https://pub.dev"
    source: hosted
    version: "2.1.2"
  google_fonts:
    dependency: "direct main"
    description:
      name: google_fonts
      sha256: e20ff62b158b96f392bfc8afe29dee1503c94fbea2cbe8186fd59b756b8ae982
      url: "https://pub.dev"
    source: hosted
    version: "5.1.0"
  graphs:
    dependency: transitive
    description:
      name: graphs
      sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19
      url: "https://pub.dev"
    source: hosted
    version: "2.3.1"
  hooks_riverpod:
    dependency: "direct main"
    description:
      name: hooks_riverpod
      sha256: "117edbe7e5cfc02e31a94f97e2acd4581f54bc37fcda9dce1f606f8ac851ba24"
      url: "https://pub.dev"
    source: hosted
    version: "2.3.7"
  hotreloader:
    dependency: transitive
    description:
      name: hotreloader
      sha256: "728c0613556c1d153f7e7f4a367cffacc3f5a677d7f6497a1c2b35add4e6dacf"
      url: "https://pub.dev"
    source: hosted
    version: "3.0.6"
  http:
    dependency: transitive
    description:
      name: http
      sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525"
      url: "https://pub.dev"
    source: hosted
    version: "1.1.0"
  http_multi_server:
    dependency: transitive
    description:
      name: http_multi_server
      sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
      url: "https://pub.dev"
    source: hosted
    version: "3.2.1"
  http_parser:
    dependency: transitive
    description:
      name: http_parser
      sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
      url: "https://pub.dev"
    source: hosted
    version: "4.0.2"
  intl:
    dependency: "direct main"
    description:
      name: intl
      sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6
      url: "https://pub.dev"
    source: hosted
    version: "0.18.0"
  intl_utils:
    dependency: "direct main"
    description:
      name: intl_utils
      sha256: a509a2ada4d12c4dc70f9ca35c2fddf75f8b402409ac1a9e1b3dd8065681986b
      url: "https://pub.dev"
    source: hosted
    version: "2.8.3"
  io:
    dependency: transitive
    description:
      name: io
      sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
      url: "https://pub.dev"
    source: hosted
    version: "1.0.4"
  js:
    dependency: transitive
    description:
      name: js
      sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
      url: "https://pub.dev"
    source: hosted
    version: "0.6.7"
  json_annotation:
    dependency: transitive
    description:
      name: json_annotation
      sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467
      url: "https://pub.dev"
    source: hosted
    version: "4.8.1"
  lints:
    dependency: transitive
    description:
      name: lints
      sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
      url: "https://pub.dev"
    source: hosted
    version: "2.1.1"
  logging:
    dependency: transitive
    description:
      name: logging
      sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
      url: "https://pub.dev"
    source: hosted
    version: "1.2.0"
  loggy:
    dependency: "direct main"
    description:
      name: loggy
      sha256: "981e03162bbd3a5a843026f75f73d26e4a0d8aa035ae060456ca7b30dfd1e339"
      url: "https://pub.dev"
    source: hosted
    version: "2.0.3"
  matcher:
    dependency: transitive
    description:
      name: matcher
      sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
      url: "https://pub.dev"
    source: hosted
    version: "0.12.15"
  material_color_utilities:
    dependency: transitive
    description:
      name: material_color_utilities
      sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
      url: "https://pub.dev"
    source: hosted
    version: "0.2.0"
  meta:
    dependency: transitive
    description:
      name: meta
      sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
      url: "https://pub.dev"
    source: hosted
    version: "1.9.1"
  mime:
    dependency: transitive
    description:
      name: mime
      sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
      url: "https://pub.dev"
    source: hosted
    version: "1.0.4"
  numeral:
    dependency: "direct main"
    description:
      name: numeral
      sha256: "3dc53e43920fe049d231665b24af760b5e2fca5f432c431f3c68cb7c0aee03f8"
      url: "https://pub.dev"
    source: hosted
    version: "2.0.1"
  package_config:
    dependency: transitive
    description:
      name: package_config
      sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
      url: "https://pub.dev"
    source: hosted
    version: "2.1.0"
  path:
    dependency: transitive
    description:
      name: path
      sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
      url: "https://pub.dev"
    source: hosted
    version: "1.8.3"
  path_provider:
    dependency: transitive
    description:
      name: path_provider
      sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2"
      url: "https://pub.dev"
    source: hosted
    version: "2.0.15"
  path_provider_android:
    dependency: transitive
    description:
      name: path_provider_android
      sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86"
      url: "https://pub.dev"
    source: hosted
    version: "2.0.27"
  path_provider_foundation:
    dependency: transitive
    description:
      name: path_provider_foundation
      sha256: "916731ccbdce44d545414dd9961f26ba5fbaa74bcbb55237d8e65a623a8c7297"
      url: "https://pub.dev"
    source: hosted
    version: "2.2.4"
  path_provider_linux:
    dependency: transitive
    description:
      name: path_provider_linux
      sha256: ffbb8cc9ed2c9ec0e4b7a541e56fd79b138e8f47d2fb86815f15358a349b3b57
      url: "https://pub.dev"
    source: hosted
    version: "2.1.11"
  path_provider_platform_interface:
    dependency: transitive
    description:
      name: path_provider_platform_interface
      sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec"
      url: "https://pub.dev"
    source: hosted
    version: "2.0.6"
  path_provider_windows:
    dependency: transitive
    description:
      name: path_provider_windows
      sha256: "1cb68ba4cd3a795033de62ba1b7b4564dace301f952de6bfb3cd91b202b6ee96"
      url: "https://pub.dev"
    source: hosted
    version: "2.1.7"
  petitparser:
    dependency: transitive
    description:
      name: petitparser
      sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750
      url: "https://pub.dev"
    source: hosted
    version: "5.4.0"
  platform:
    dependency: transitive
    description:
      name: platform
      sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76"
      url: "https://pub.dev"
    source: hosted
    version: "3.1.0"
  plugin_platform_interface:
    dependency: transitive
    description:
      name: plugin_platform_interface
      sha256: "43798d895c929056255600343db8f049921cbec94d31ec87f1dc5c16c01935dd"
      url: "https://pub.dev"
    source: hosted
    version: "2.1.5"
  pointycastle:
    dependency: transitive
    description:
      name: pointycastle
      sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
      url: "https://pub.dev"
    source: hosted
    version: "3.7.3"
  pool:
    dependency: transitive
    description:
      name: pool
      sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
      url: "https://pub.dev"
    source: hosted
    version: "1.5.1"
  pub_semver:
    dependency: transitive
    description:
      name: pub_semver
      sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
      url: "https://pub.dev"
    source: hosted
    version: "2.1.4"
  pubspec_parse:
    dependency: transitive
    description:
      name: pubspec_parse
      sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367
      url: "https://pub.dev"
    source: hosted
    version: "1.2.3"
  riverpod:
    dependency: transitive
    description:
      name: riverpod
      sha256: "80e48bebc83010d5e67a11c9514af6b44bbac1ec77b4333c8ea65dbc79e2d8ef"
      url: "https://pub.dev"
    source: hosted
    version: "2.3.6"
  riverpod_analyzer_utils:
    dependency: transitive
    description:
      name: riverpod_analyzer_utils
      sha256: "1b2632a6fc0b659c923a4dcc7cd5da42476f5b3294c70c86c971e63bdd443384"
      url: "https://pub.dev"
    source: hosted
    version: "0.3.1"
  riverpod_annotation:
    dependency: "direct main"
    description:
      name: riverpod_annotation
      sha256: cedd6a54b6f5764ffd5c05df57b6676bfc8c01978e14ee60a2c16891038820fe
      url: "https://pub.dev"
    source: hosted
    version: "2.1.1"
  riverpod_generator:
    dependency: "direct dev"
    description:
      name: riverpod_generator
      sha256: "691180275664a5420c87d72c1ed26ef8404d32b823807540172bfd1660425376"
      url: "https://pub.dev"
    source: hosted
    version: "2.2.4"
  riverpod_lint:
    dependency: "direct dev"
    description:
      name: riverpod_lint
      sha256: "17ad319914ac6863c64524e598913c0f17e30688aca8f5b7509e96d6e372d493"
      url: "https://pub.dev"
    source: hosted
    version: "1.4.0"
  rxdart:
    dependency: transitive
    description:
      name: rxdart
      sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb"
      url: "https://pub.dev"
    source: hosted
    version: "0.27.7"
  shelf:
    dependency: transitive
    description:
      name: shelf
      sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
      url: "https://pub.dev"
    source: hosted
    version: "1.4.1"
  shelf_web_socket:
    dependency: transitive
    description:
      name: shelf_web_socket
      sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1"
      url: "https://pub.dev"
    source: hosted
    version: "1.0.4"
  sky_engine:
    dependency: transitive
    description: flutter
    source: sdk
    version: "0.0.99"
  source_gen:
    dependency: transitive
    description:
      name: source_gen
      sha256: fc0da689e5302edb6177fdd964efcb7f58912f43c28c2047a808f5bfff643d16
      url: "https://pub.dev"
    source: hosted
    version: "1.4.0"
  source_span:
    dependency: transitive
    description:
      name: source_span
      sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
      url: "https://pub.dev"
    source: hosted
    version: "1.9.1"
  squadron:
    dependency: "direct main"
    description:
      name: squadron
      sha256: b2dd9457091063e7744a71f6d842daae7cb67eadcd8a3c2c5a2b18f6b9d2d664
      url: "https://pub.dev"
    source: hosted
    version: "5.1.3"
  squadron_builder:
    dependency: "direct main"
    description:
      name: squadron_builder
      sha256: "5df2be97d8f18a9a7f25b22d8ff1b81449ebcbc916343abb3f8a949b3a379396"
      url: "https://pub.dev"
    source: hosted
    version: "2.4.1"
  stack_trace:
    dependency: transitive
    description:
      name: stack_trace
      sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
      url: "https://pub.dev"
    source: hosted
    version: "1.11.0"
  state_notifier:
    dependency: transitive
    description:
      name: state_notifier
      sha256: "8fe42610f179b843b12371e40db58c9444f8757f8b69d181c97e50787caed289"
      url: "https://pub.dev"
    source: hosted
    version: "0.7.2+1"
  stream_channel:
    dependency: transitive
    description:
      name: stream_channel
      sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
      url: "https://pub.dev"
    source: hosted
    version: "2.1.1"
  stream_transform:
    dependency: transitive
    description:
      name: stream_transform
      sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f"
      url: "https://pub.dev"
    source: hosted
    version: "2.1.0"
  string_scanner:
    dependency: transitive
    description:
      name: string_scanner
      sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
      url: "https://pub.dev"
    source: hosted
    version: "1.2.0"
  term_glyph:
    dependency: transitive
    description:
      name: term_glyph
      sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
      url: "https://pub.dev"
    source: hosted
    version: "1.2.1"
  test_api:
    dependency: transitive
    description:
      name: test_api
      sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
      url: "https://pub.dev"
    source: hosted
    version: "0.5.1"
  timing:
    dependency: transitive
    description:
      name: timing
      sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32"
      url: "https://pub.dev"
    source: hosted
    version: "1.0.1"
  typed_data:
    dependency: transitive
    description:
      name: typed_data
      sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
      url: "https://pub.dev"
    source: hosted
    version: "1.3.2"
  uuid:
    dependency: "direct main"
    description:
      name: uuid
      sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"
      url: "https://pub.dev"
    source: hosted
    version: "3.0.7"
  vector_math:
    dependency: transitive
    description:
      name: vector_math
      sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
      url: "https://pub.dev"
    source: hosted
    version: "2.1.4"
  vm_service:
    dependency: transitive
    description:
      name: vm_service
      sha256: ada49637c27973c183dad90beb6bd781eea4c9f5f955d35da172de0af7bd3440
      url: "https://pub.dev"
    source: hosted
    version: "11.8.0"
  watcher:
    dependency: transitive
    description:
      name: watcher
      sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
      url: "https://pub.dev"
    source: hosted
    version: "1.1.0"
  web_socket_channel:
    dependency: transitive
    description:
      name: web_socket_channel
      sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
      url: "https://pub.dev"
    source: hosted
    version: "2.4.0"
  win32:
    dependency: transitive
    description:
      name: win32
      sha256: f2add6fa510d3ae152903412227bda57d0d5a8da61d2c39c1fb022c9429a41c0
      url: "https://pub.dev"
    source: hosted
    version: "5.0.6"
  xdg_directories:
    dependency: transitive
    description:
      name: xdg_directories
      sha256: e0b1147eec179d3911f1f19b59206448f78195ca1d20514134e10641b7d7fbff
      url: "https://pub.dev"
    source: hosted
    version: "1.0.1"
  yaml:
    dependency: transitive
    description:
      name: yaml
      sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
      url: "https://pub.dev"
    source: hosted
    version: "3.1.2"
sdks:
  dart: ">=3.0.6 <4.0.0"
  flutter: ">=3.10.0"
Code
import 'dart:async';

import 'package:squadron/squadron.dart';
import 'package:squadron/squadron_annotations.dart';

import 'live_feed.activator.g.dart';

part 'live_feed.worker.g.dart';

@SquadronService()
class LiveFeedService implements WorkerService {
  @SquadronMethod()
  Stream<double> pulse() async* {
    var n = 0;
    while (true) {
      yield n.toDouble();
      n += 1;
      await Future.delayed(const Duration(milliseconds: 100));
    }
  }

  @override
  Map<int, CommandHandler> get operations => throw UnimplementedError();
}

Generated

// GENERATED CODE - DO NOT MODIFY BY HAND

// **************************************************************************
// Generator: WorkerGenerator 2.4.1
// **************************************************************************

import 'live_feed.stub.g.dart'
    if (dart.library.js) 'live_feed.web.g.dart'
    if (dart.library.html) 'live_feed.web.g.dart'
    if (dart.library.io) 'live_feed.vm.g.dart';

/// Service activator for LiveFeedService
final $LiveFeedServiceActivator = $getLiveFeedServiceActivator();
// GENERATED CODE - DO NOT MODIFY BY HAND

// **************************************************************************
// Generator: WorkerGenerator 2.4.1
// **************************************************************************

import 'package:squadron/squadron.dart';

EntryPoint $getLiveFeedServiceActivator() => throw UnimplementedError();
// GENERATED CODE - DO NOT MODIFY BY HAND

// **************************************************************************
// Generator: WorkerGenerator 2.4.1
// **************************************************************************

import 'package:squadron/squadron.dart';

import 'live_feed.dart';

/// VM entry point for LiveFeedService
void _start$LiveFeedService(List<dynamic> command) =>
    run($LiveFeedServiceInitializer, command, null);

EntryPoint $getLiveFeedServiceActivator() => _start$LiveFeedService;
// GENERATED CODE - DO NOT MODIFY BY HAND

// **************************************************************************
// Generator: WorkerGenerator 2.4.1
// **************************************************************************

import 'package:squadron/squadron.dart';

import 'live_feed.dart';

void main() {
  /// Web entry point for LiveFeedService
  run($LiveFeedServiceInitializer, null, null);
}

EntryPoint $getLiveFeedServiceActivator() =>
    'lib/service/live_feed/live_feed.web.g.dart.js';
// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'live_feed.dart';

// **************************************************************************
// Generator: WorkerGenerator 2.4.1
// **************************************************************************

/// WorkerService class for LiveFeedService
class _$LiveFeedServiceWorkerService extends LiveFeedService
    implements WorkerService {
  _$LiveFeedServiceWorkerService() : super();

  @override
  Map<int, CommandHandler> get operations => _operations;

  late final Map<int, CommandHandler> _operations = {_$pulseId: ($) => pulse()};

  static const int _$pulseId = 1;
}

/// Service initializer for LiveFeedService
WorkerService $LiveFeedServiceInitializer(WorkerRequest startRequest) =>
    _$LiveFeedServiceWorkerService();

/// Operations map for LiveFeedService
@Deprecated(
    'squadron_builder now supports "plain old Dart objects" as services. '
    'Services do not need to derive from WorkerService nor do they need to mix in '
    'with \$LiveFeedServiceOperations anymore.')
mixin $LiveFeedServiceOperations on WorkerService {
  @override
  // not needed anymore, generated for compatibility with previous versions of squadron_builder
  Map<int, CommandHandler> get operations => WorkerService.noOperations;
}

/// Worker for LiveFeedService
class LiveFeedServiceWorker extends Worker implements LiveFeedService {
  LiveFeedServiceWorker({PlatformWorkerHook? platformWorkerHook})
      : super($LiveFeedServiceActivator,
            platformWorkerHook: platformWorkerHook);

  @override
  Stream<double> pulse() =>
      stream(_$LiveFeedServiceWorkerService._$pulseId, args: []);

  @override
  Map<int, FutureOr<dynamic> Function(List<dynamic>)> get operations =>
      throw UnimplementedError();
}

/// Worker pool for LiveFeedService
class LiveFeedServiceWorkerPool extends WorkerPool<LiveFeedServiceWorker>
    implements LiveFeedService {
  LiveFeedServiceWorkerPool(
      {ConcurrencySettings? concurrencySettings,
      PlatformWorkerHook? platformWorkerHook})
      : super(
            () => LiveFeedServiceWorker(platformWorkerHook: platformWorkerHook),
            concurrencySettings: concurrencySettings);

  @override
  Stream<double> pulse() => stream((w) => w.pulse());

  @override
  Map<int, FutureOr<dynamic> Function(List<dynamic>)> get operations =>
      throw UnimplementedError();
}

Worker trigger at startup.

void main() async {
  Loggy.initLoggy(
    logOptions: LogOptions(
      LogLevel.values
          .firstWhere((level) => level.priority == ConfigValues.logLevel),
    ),
  );

  final worker = LiveFeedServiceWorker();

  await worker.start();

  runApp(
    ProviderScope(
      overrides: [],
      observers: [if (ConfigValues.observeProviders) ProviderDebugObserver()],
      child: const WrkAteEdgeApp(
        appVersion: ConfigValues.appVersion,
        showDebugBanner: ConfigValues.showDebugBanner,
      ),
    ),
  );
}

I have tried

  1. clean and rebuild.
  2. using a build.yaml to direct where the generated files land.
  3. calling start lower in the tree, like within a Widget.
  4. specifying a base url in the annotation.

So I am at a bit of a lost, it 'Appears' to work for Android but certainly not on the web.

No documentation for release mode

When building using flutter build web, the app always throws an error that it couldn't locate the worker.dart.js we created.

I had to add this script in my index.html to get it to load.

  <!-- Load our solver_worker.dart.js file-->
  <script>
    const scriptTag = document.createElement('script');
    scriptTag.src = 'solver_worker.dart.js';
    scriptTag.defer = true;
    scriptTag.type = 'text/javascript';
    document.body.append(scriptTag);
  </script>

Provide access to webworker instance.

I know this might not make sense for the general case using squadron, but I need to install a message handler outside of squadron directly on the web worker itself at creation time to handle some pre-existing javascript shims when targeting the browser.

I forked squadron and just added my handler manually as a quick solution, but I'm wondering if it would make sense to provide a way to pass a call back that recieves the webworker directly when initializing the service.

Currently web worker creation looks like this.

final channel = _JsChannel._();
final com = web.MessageChannel();
final worker = web.Worker(entryPoint);

I would like to do something like this, with onCreateWorker being a callback passed in at service instantiation.

 final channel = _JsChannel._(); 
 final com = web.MessageChannel(); 
 final worker = web.Worker(entryPoint); 
 onCreateWorker(worker);

Event loop is stuck on await

Hi, I have a simple squadron class.

@SquadronService(baseUrl: '/services/websocket')
class WebSocketService {
  WebSocketService({required this.url}): _client = WebSocketClient(url: url);

  final String url;
  final WebSocketClient _client;

  @SquadronMethod()
  Future<void> connect() async {
    ...
  }

  @SquadronMethod()
  Future<void> disconnect() async {
    ...
  }

  @SquadronMethod()
  Future<void> closeConnection() async {
    print('I am closing connection');
    await _client.close();
    print('I am returning');
  }
}

Everything works great! All Thanks to your wonderful package.

I am trying to make sure that the WebSocket client is closed when the mobile app is detached.

appLifecycleListener = AppLifecycleListener(
      onDetach: () async {
        print('I am disposing');
        final wsPool = ...; // This workerPool only has at most 1 worker 
        await wsPool.closeConnection();
        print('I am successful');
      },
);

Logs:

I am disposing
I am closing connection
I am returning

I have made sure to handle all the errors properly. I do not get any errors. App runs and closes perfectly. But the print message 'I am successful' is not called. The event loop is stuck on awaiting wsPool.closeConnection() event though the closeConnection() method is already completed.

This is the simplification of my issue.

The original issue I am facing is that I am closing the connection and stopping the worker pool. Since closing the connection is asynchronous and stopping the worker pool is synchronous, the event loop first stops the worker pool and then closes the connection which is an error (await keyword is missing). But I cannot add await else the event loop is stuck as seen above. I have tried to stop the worker pool asynchronously to make sure closeConnection is called first before stopping the worker pool as below:

Future.delayed(Duration.zero, () {
   // Doesn't get called if the code below or above this Future has wsPool.closeConnection(); 
    wsPool.stop();
  });

Future.delayed(const Duration(seconds: 1), () {
   // Doesn't get called if the code below or above this Future has wsPool.closeConnection(); 
    wsPool.stop();
});

Timer(Duration(seconds: 1), () {
   // Doesn't get called if the code below or above this Future has wsPool.closeConnection(); 
    wsPool.stop();
});

I have spent the whole day fighting with this bug but I am still unable to find the root cause of it.

About throwing Exception from worker

I implemented this custom class that I wanted to throw from worker.

class HttpException extends WorkerException {
  HttpException({final String? message})
      : super(message ?? 'Received a response with non-successful status code');
}

It works but its toString() method is too verbose. It's serialized into a list in the pattern: [int, message, WorkerException]

I wanted to only return the message.

class HttpException extends WorkerException {
  HttpException({final String? message})
      : super(message ?? 'Received a response with non-successful status code');

  @override
  String toString() {
    return message;
  }
}

But that does no effect. How should I handle this ?

[Feature Req] Add a binary reader/writer with nice API to marshal data

Not sure if you're familiar with the hive flutter library. If you're not, they basically allow the user to create type adapters to marshal/unmarshal the data with a fairly nice API. See example here: https://docs.hivedb.dev/#/custom-objects/create_adapter_manually

The main code for the reader and writer is in those 2 files:
https://github.com/isar/hive/blob/legacy/hive/lib/src/binary/binary_writer_impl.dart
https://github.com/isar/hive/blob/legacy/hive/lib/src/binary/binary_reader_impl.dart

Replicating/cherrypicking the binary reader/writer (or even extracting it into a library) could make using SquadronMarshaler a lot easier.

P.s. I personally spent 10 mins to copy the code into my own repo and make use of it. I think everyone could benefit if this is directly part of squadron

P.p.s. While it may be nice, don't think there's a need to add handling for custom types and register adapters (the way hive does it). Just a simple binary reader/writer should be more than enough to improve usability.

how to compile .js for the web?

Hello! Thank you for the awesome plugin. I'm having a little difficulty while compiling the js file to use worker on the web. would it be possible to have your guidance on the issue?

this is my original file

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:squadron/squadron.dart';
import 'package:squadron/squadron_annotations.dart';

import 'work.activator.g.dart';

part 'work.worker.g.dart';

@SquadronService(pool: false)
class Work {
 Offset oldOff = Offset.zero;
 @SquadronMethod()
 Future<void> updateElements(Offset n) async {
   oldOff = n;
 }
}


i genrated code with squadron_builder package and got the work.web.g.dart file

now when i run the work.web.g.dart to js compile it throws errros

                                                            ^^^^^^^^^^^^^^^^^
../../../flutter/packages/flutter/lib/src/gestures/monodrag.dart:681:23:
Error: The method 'clampDouble' isn't defined for the class 'HorizontalDragGestureRecognizer'.
 - 'HorizontalDragGestureRecognizer' is from 'package:flutter/src/gestures/monodrag.dart' ('../../../flutter/packages/flutter/lib/src/gestures/monodrag.dart').
    final double dx = clampDouble(estimate.pixelsPerSecond.dx, -maxVelocity, maxVelocity);
                      ^^^^^^^^^^^
../../../flutter/packages/flutter/lib/src/gestures/monodrag.dart:683:43:
Error: The method 'Offset' isn't defined for the class 'HorizontalDragGestureRecognizer'.
 - 'HorizontalDragGestureRecognizer' is from 'package:flutter/src/gestures/monodrag.dart' ('../../../flutter/packages/flutter/lib/src/gestures/monodrag.dart').
      velocity: Velocity(pixelsPerSecond: Offset(dx, 0)),
                                          ^^^^^^
../../../flutter/packages/flutter/lib/src/gestures/monodrag.dart:689:45:
Error: 'PointerDeviceKind' isn't a type.
  bool _hasSufficientGlobalDistanceToAccept(PointerDeviceKind pointerDeviceKind, double? deviceTouchSlop) {
                                            ^^^^^^^^^^^^^^^^^
../../../flutter/packages/flutter/lib/src/gestures/monodrag.dart:694:30:
Error: 'Offset' isn't a type.
  Offset _getDeltaForDetails(Offset delta) => Offset(delta.dx, 0.0);
                             ^^^^^^
../../../flutter/packages/flutter/lib/src/gestures/monodrag.dart:694:47:
Error: The method 'Offset' isn't defined for the class 'HorizontalDragGestureRecognizer'.
 - 'HorizontalDragGestureRecognizer' is from 'package:flutter/src/gestures/monodrag.dart' ('../../../flutter/packages/flutter/lib/src/gestures/monodrag.dart').
  Offset _getDeltaForDetails(Offset delta) => Offset(delta.dx, 0.0);
                                              ^^^^^^
../../../flutter/packages/flutter/lib/src/gestures/monodrag.dart:697:37:
Error: 'Offset' isn't a type.
  double _getPrimaryValueFromOffset(Offset value) => value.dx;
                                    ^^^^^^
../../../flutter/packages/flutter/lib/src/gestures/monodrag.dart:721:50:
Error: 'PointerDeviceKind' isn't a type.
  bool isFlingGesture(VelocityEstimate estimate, PointerDeviceKind kind) {
                                                 ^^^^^^^^^^^^^^^^^
../../../flutter/packages/flutter/lib/src/gestures/monodrag.dart:729:61:
Error: 'PointerDeviceKind' isn't a type.
  DragEndDetails? _considerFling(VelocityEstimate estimate, PointerDeviceKind kind) {
                                                            ^^^^^^^^^^^^^^^^^
../../../flutter/packages/flutter/lib/src/gestures/monodrag.dart:739:45:
Error: 'PointerDeviceKind' isn't a type.
  bool _hasSufficientGlobalDistanceToAccept(PointerDeviceKind pointerDeviceKind, double? deviceTouchSlop) {
                                            ^^^^^^^^^^^^^^^^^
../../../flutter/packages/flutter/lib/src/gestures/monodrag.dart:744:30:
Error: 'Offset' isn't a type.
  Offset _getDeltaForDetails(Offset delta) => delta;
                             ^^^^^^

...............

..............

i have to import Offset class anyways

Expected a value of type 'Map<String, Object?>' but got one of type 'LinkedMap<dynamic, dynamic>'

I am returning this model class from squadron worker. Why is it that this works on isolates but not on web workers ? I do not see any data type that should not be transferred from web worker but still I am getting an exception. There are fromJson and toJson methods that work on Dart VM but not on web.

class HttpResponse extends Response {
  factory HttpResponse.fromJson(final Map<String, Object?> json) {
    return HttpResponse._bytes(
      json['bodyBytes']! as List<int>,
      json['statusCode']! as int,
      headers: json['headers']! as Map<String, String>,
      isRedirect: json['isRedirect']! as bool,
      persistentConnection: json['persistentConnection']! as bool,
      reasonPhrase: json['reasonPhrase'] as String?,
    );
  }
  HttpResponse._bytes(super.bodyBytes, super.statusCode,
      {super.headers,
      super.isRedirect,
      super.persistentConnection,
      super.reasonPhrase})
      : super.bytes();

  factory HttpResponse.fromResponse(final Response response) {
    return HttpResponse._bytes(
      response.bodyBytes,
      response.statusCode,
      headers: response.headers,
      isRedirect: response.isRedirect,
      persistentConnection: response.persistentConnection,
      reasonPhrase: response.reasonPhrase,
    );
  }

  Map<String, Object?> toJson() => {
        'bodyBytes': bodyBytes,
        'statusCode': statusCode,
        'headers': headers,
        'isRedirect': isRedirect,
        'persistentConnection': persistentConnection,
        'reasonPhrase': reasonPhrase,
      };
}

Here is the exception (Screenshot):

image

WorkerException: error in Web Worker #976509285: /workers/solver_worker.dart.js: error / [object Event]

I got the dart js command to run this time. Turns out, the SDK (that we made) that the solver classes depend on was depending on dart:ui classes for unrelated sections of the api.

I guess the dart js command isn't smart enough to tree-shake all the code that isn't being used by our api accessors.

Point is, I made a copy of the sdk and stripped it down heavely to only bare-minimum data without relying on any dart:ui or flutter code, and it worked. I compiled the js file and moved it into the web folder, but it's crashing and the error message is not useful unfortunately.

Maybe it's because it's a js file compiled from a completely separate and incompatible copy of the sdk, but in any case, an error message would go a long way.

Here's the ouput after running the project in a chrome browser:

WorkerException: error in Web Worker #976509285: /workers/solver_worker.dart.js: error / [object Event]
dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 906:28                get current
packages/squadron/src/worker_exception.dart 7:55                                  new
packages/squadron/src/browser/channel.dart 223:11                                 <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 334:14  _checkAndCall
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 339:39  dcall
dart-sdk/lib/html/dart2js/html_dart2js.dart 37230:58                              <fn>
dart-sdk/lib/async/zone.dart 1444:13                                              _rootRunUnary
dart-sdk/lib/async/zone.dart 1335:19                                              runUnary
dart-sdk/lib/async/zone.dart 1244:7                                               runUnaryGuarded
dart-sdk/lib/async/zone.dart 1281:26                                              <fn>

Error: The argument type 'Map<dynamic, dynamic>' can't be assigned to the parameter type 'List<dynamic>?'

Hey ๐Ÿ‘‹

I'm using squadron 5.0.0 with squadron_builder 2.1.2 and get this error when compiling my app.

lib/src/core/api/data/service/json_service.vm.g.dart:11:58: Error: The argument type 'Map<dynamic, dynamic>' can't be assigned to the parameter type 'List<dynamic>?'.
 - 'Map' is from 'dart:core'.
 - 'List' is from 'dart:core'.
void _start(Map command) => run($JsonServiceInitializer, command, null);
                                                         ^
Target kernel_snapshot failed: Exception

does this package work with freezed?

Hi

does this package work with freezed? if yes can you show an example from the code below?

its fromJson, and toJson that i want to use.

Thanks.

@freezed
class ProfileDTO with _$ProfileDTO {
  const factory ProfileDTO({
    required int id,
    required String name,
  }) = _ProfileDTO;
  const ProfiletDTO._();
  factory ProfileDTO.fromJson(Map<String, dynamic> json) =>
      _$ProfileDTOFromJson(json);

}

Will every worker in a pool share the same resource ?

I was wondering if the workers in a pool share the same client, or each worker will have its own client in the following code. If they do not share the same client, then I will have to manually call the closeConnection() method by listening when the worker is removed in the workerpool in which case the callback should be called before the worker is actually removed.

SquadronService(baseUrl: '/services')
class HttpService {
  HttpService() : _client = Client();

  late final BaseClient _client;

  @SquadronMethod()
  Future<void> closeConnection() async {
    _client.close();
  }
}

Also, will the client be initialized when a worker pool is started or will it defer until the worker is started?

Unable to throw on a stream from web

Hi - me again.

Consider this code in a service:

class ParserService implements WorkerService {
  Stream<SignalValue> streamParser(List<dynamic> words) async* {
    int id = 0;
    for (var word in words) {
      await Future.delayed(const Duration(milliseconds: 500));
      if (id == 2) throw 'this is an error';
      yield SignalValue(signalDecimalValue: ++id, interval: id, idCode: word);
    }
  }

  // command IDs
  static const streamCommand = 1;

  // command IDs --> command implementations
  @override
  Map<int, CommandHandler> get operations => {
        streamCommand: (r) =>
            streamParser(r.args[0]).map((sv) => sv.serialize()),
      };
}

In the web version, with the pool.stream, I can listen, but the onError parameter doesn't get called as a result of the throw. When I run this on the non-web version, it works as expected, where the throw calls on the onError parameter in the main thread.

I wanted to check, is this a bug; or a limitation of streams on the web version?

Thanks,
Martin

Unable to pass serialized Channel between web workers

I have been messing around with Squadron, and have to say I am very impressed, but I have run into an issue when attempting to pass Channels from one web worker to another.

Example:

///main.dart
import 'package:squadron/squadron.dart';

import 'js_test_worker.dart';

void main() async {
  Squadron.setId('MAIN');
  Squadron.debugMode = true;
  Squadron.setLogger(ConsoleSquadronLogger());

  final testWorker1 = createJsSampleWorker();
  await testWorker1.start();

  final testWorker2 = createJsSampleWorker();
  await testWorker2.setChannel(testWorker1.channel?.share().serialize());
}
///test_worker.dart
import 'package:squadron/squadron.dart';

import 'test_service.dart';

class TestWorker extends Worker implements TestService {
  TestWorker(dynamic entryPoint, {List args = const []})
      : super(entryPoint, args: args);

  @override
  Future<String> test() => send(TestService.testCommand);

  @override
  Future<void> setChannel(Object channelInfo) =>
      send(TestService.setChannelCommand, args: [channelInfo]);
}
///test_service.dart
import 'dart:async';

import 'package:squadron/squadron.dart';

abstract class TestService {
  FutureOr<String> test();
  FutureOr setChannel(Object channelInfo);

  // command IDs
  static const testCommand = 1;
  static const setChannelCommand = 2;
}

class TestServiceImpl implements TestService, WorkerService {
  int value = 0;
  Channel? testChannel;

  @override
  Future<String> test() async {
    return 'this is a test ${value++}';
  }

  @override
  void setChannel(Object channelInfo) async {
    testChannel = Channel.deserialize(channelInfo);
    var result = await testChannel!.sendRequest(TestService.testCommand, []);
    print(result);
  }

  // command IDs --> command handlers
  @override
  late final Map<int, CommandHandler> operations = {
    TestService.testCommand: (WorkerRequest r) => test(),
    TestService.setChannelCommand: (WorkerRequest r) => setChannel(r.args[0]),
  };
}
///js_test_worker.dart
import 'package:squadron/squadron_service.dart';

import 'test_worker.dart';
import 'test_service.dart';

// // dart compile js lib/js_test_worker.dart -o web/js_test_worker.dart.js -m
TestWorker createJsSampleWorker() => TestWorker('js_test_worker.dart.js');

// Web Worker entry-point.
// It must be a parameter-less "main()" function.
void main() => run((startRequest) => TestServiceImpl());
[2022-07-15T16:32:19.438Z] [SEVERE] [MAIN] failed to post request {a: [object MessagePort], b: 2, c: [[object MessagePort]], h: false}: error DataCloneError: Failed to execute 'postMessage' on 'MessagePort': A MessagePort could not be cloned because it was not transferred.
Error: ["$W","DataCloneError: Failed to execute 'postMessage' on 'MessagePort': A MessagePort could not be cloned because it was not transferred.","C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/html/dart2js/html_dart2js.dart 21737:3                  [_postMessage_1]\nC:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/html/dart2js/html_dart2js.dart 21731:7                  postMessage]\npackages/squadron/src/browser/_channel.dart 41:7                                                                  [_postRequest]\npackages/squadron/src/xplat/_value_wrapper.dart 61:16                                                             compute\npackages/squadron/src/browser/_channel.dart 96:19                                                                 sendRequest\npackages/squadron/src/worker.dart 119:30                                                                          send\nC:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 45:50   <fn>\nC:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/zone.dart 1685:54                                 runUnary\nC:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 147:18                           handleValue\nC:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 766:44                           handleValueCallback\nC:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 795:13                           _propagateToListeners\nC:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 566:5                            [_completeWithValue]\nC:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 639:7                            callback\nC:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/schedule_microtask.dart 40:11                     _microtaskLoop\nC:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/schedule_microtask.dart 49:5                      _startMicrotaskLoop\nC:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 166:15  <fn>\n","MAIN.2",2]
    at Object.throw_ [as throw] (http://localhost:17986/dart_sdk.js:5080:11)
at test_worker.TestWorker.new.send (http://localhost:17986/packages/squadron/src/squadron_logger.dart.lib.js:1387:19)
    at send.next (<anonymous>)
    at http://localhost:17986/dart_sdk.js:40641:33
    at _RootZone.runUnary (http://localhost:17986/dart_sdk.js:40511:59)
    at _FutureListener.thenAwait.handleValue (http://localhost:17986/dart_sdk.js:35438:29)
    at handleValueCallback (http://localhost:17986/dart_sdk.js:35999:49)
    at _Future._propagateToListeners (http://localhost:17986/dart_sdk.js:36037:17)
    at [_completeWithValue] (http://localhost:17986/dart_sdk.js:35872:23)
    at async._AsyncCallbackEntry.new.callback (http://localhost:17986/dart_sdk.js:35906:35)
    at Object._microtaskLoop (http://localhost:17986/dart_sdk.js:40778:13)
    at _startMicrotaskLoop (http://localhost:17986/dart_sdk.js:40784:13)
    at http://localhost:17986/dart_sdk.js:36261:9

Not sure if this is an actual issue or just a user error on my part, but in either case, it would be nice to have some additional examples of how to send Channels between web workers, and how to use those Channels to pass data between workers.

Error: Expected a value of type 'String', but got one of type '(Map<dynamic, dynamic>) => void'

Just want to ask maybe you can give me a hint on this error? Running on web target in Chromium: Version 110.0.5481.77 (Official Build) Fedora Project (64-bit)

Error: Expected a value of type 'String', but got one of type '(Map<dynamic, dynamic>) => void'
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 288:49      throw_
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 121:3       castError
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 529:12  cast
dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 704:17                as
packages/squadron/src/browser/_channel.dart 277:22                                openChannel
packages/squadron/src/channel.dart 54:7                                           open
packages/squadron/src/worker.dart 207:32                                          start
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 84:54                runBody
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 123:5                _async
packages/squadron/src/worker.dart 202:24                                          start
packages/squadron/src/worker.dart 115:23                                          send
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 84:54                runBody
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 123:5                _async
packages/squadron/src/worker.dart 99:20                                           send
packages/frame/services/vk_service.dart 191:26                                    init
packages/frame/main.dart 32:20                                                    main$
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 84:54                runBody
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 123:5                _async
packages/frame/main.dart 29:10                                                    main$
web_entrypoint.dart 24:31                                                         <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 367:37  _checkAndCall
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 372:39  dcall
lib/ui/initialization.dart 77:15                                                  <fn>
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 45:50                <fn>
dart-sdk/lib/async/zone.dart 1660:54                                              runUnary
dart-sdk/lib/async/future_impl.dart 147:18                                        handleValue
dart-sdk/lib/async/future_impl.dart 784:44                                        handleValueCallback
dart-sdk/lib/async/future_impl.dart 813:13                                        _propagateToListeners
dart-sdk/lib/async/future_impl.dart 584:5                                         [_completeWithValue]
dart-sdk/lib/async/future_impl.dart 657:7                                         callback
dart-sdk/lib/async/schedule_microtask.dart 40:11                                  _microtaskLoop
dart-sdk/lib/async/schedule_microtask.dart 49:5                                   _startMicrotaskLoop
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 177:15               <fn>

flutter doctor:

Doctor summary (to see all details, run flutter doctor -v):
[โœ“] Flutter (Channel master, 3.8.0-15.0.pre.1, on Fedora Linux 37 (Workstation Edition) 6.1.12-200.fc37.x86_64, locale
    en_US.UTF-8)
[โœ“] Android toolchain - develop for Android devices (Android SDK version 33.0.2)
[โœ“] Chrome - develop for the web
[โœ“] Linux toolchain - develop for Linux desktop
[โœ“] Android Studio (version 2022.1)
[โœ“] VS Code (version 1.75.1)
[โœ“] Connected device (3 available)
[โœ“] Network resources

โ€ข No issues found!

Squadron: ^4.3.3

Web: Error: No 'main' method found.

Hello! I'm testing your lib and it's working fine for desktop (macOS). Now I'm trying for the web but I got this error:

image

Any ideas?

Dart SDK version: 3.3.4 (stable) (Tue Apr 16 19:56:12 2024 +0000) on "macos_arm64"

http constraint too high

Hey,

I think that the http: ^1.0.0 constraint is too draconian as a lot of packages still haven't adopted 1.0.0.

I would sugges a more flexible approach like

http: ">=0.13.6 <2.0.0"

Running native plugins in squadron isolates

So I get this error message when trying to run a native decoder plugin with a squadron setup.
Bad state: The BackgroundIsolateBinaryMessenger.instance value is invalid until BackgroundIsolateBinaryMessenger.ensureInitialized is executed.
I've been down the rabbit hole a bit with this and I've found this:
flutter/flutter#119207
which is about not being able to do event streaming from platform back to dart on an isolate. That I have a workaround for so, while disappointing, I can get past.
And then there's this guy
lamnhan066/isolate_manager#5
which is the same error message I get although using a different package. But they suggest passing in that rootInstanceToken to your compute isolates.
I tried what I would think would be analogous in squadron but I'm still getting the error. Do you have any pro tips or breadcrumbs that can get this working for me. I'd love to not have to do my decoder threads on the main isolate.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.