Skip to content

Commit 9f08c16

Browse files
Merge pull request #11 from MelbourneDeveloper/asynclocking
Async Locking
2 parents d9fdc10 + c6fedad commit 9f08c16

File tree

9 files changed

+301
-231
lines changed

9 files changed

+301
-231
lines changed

.github/workflows/build_and_test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020

2121
- uses: subosito/flutter-action@v2
2222
with:
23-
flutter-version: "3.7.5"
23+
flutter-version: "3.10.6"
2424
channel: "stable"
2525
cache: true
2626
cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:"
@@ -33,7 +33,7 @@ jobs:
3333
run: dart analyze lib --no-fatal-warnings
3434

3535
- name: Check Formatting
36-
run: flutter format lib --set-exit-if-changed
36+
run: dart format lib --set-exit-if-changed
3737

3838
- name: Run Tests
3939
run: flutter test --coverage --update-goldens

analysis_options.yaml

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,3 @@
11
include: package:austerity/analysis_options.yaml
22

3-
dart_code_metrics:
4-
anti-patterns:
5-
- long-method:
6-
severity: error
7-
- long-parameter-list:
8-
severity: error
9-
metrics:
10-
cyclomatic-complexity: 20
11-
maximum-nesting-level: 5
12-
number-of-parameters: 4
13-
source-lines-of-code: 50
14-
weight-of-class: 0.33
15-
halstead-volume: 150
16-
metrics-exclude:
17-
rules:
18-
- newline-before-return:
19-
severity: error
20-
- no-boolean-literal-compare:
21-
severity: error
22-
- no-empty-block:
23-
severity: error
24-
- prefer-trailing-comma:
25-
severity: error
26-
- prefer-conditional-expressions:
27-
severity: error
28-
- no-equal-then-else:
29-
severity: error
30-
- avoid-restricted-imports:
31-
severity: error
32-
- avoid-global-state:
33-
severity: error
34-
- avoid-ignoring-return-values:
35-
severity: warning
36-
- avoid-late-keyword:
37-
severity: error
3+

benchmarks/pubspec.lock

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,13 @@ packages:
153153
url: "https://pub.dev"
154154
source: hosted
155155
version: "1.0.3"
156+
ioc_container:
157+
dependency: "direct main"
158+
description:
159+
path: ".."
160+
relative: true
161+
source: path
162+
version: "1.0.12"
156163
js:
157164
dependency: transitive
158165
description:
@@ -418,4 +425,4 @@ packages:
418425
source: hosted
419426
version: "3.1.1"
420427
sdks:
421-
dart: ">=2.18.2 <3.0.0"
428+
dart: ">=2.18.2 <4.0.0"

example/pubspec.lock

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ packages:
55
dependency: transitive
66
description:
77
name: async
8-
sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0
8+
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
99
url: "https://pub.dev"
1010
source: hosted
11-
version: "2.10.0"
11+
version: "2.11.0"
1212
austerity:
1313
dependency: "direct dev"
1414
description:
@@ -29,10 +29,10 @@ packages:
2929
dependency: transitive
3030
description:
3131
name: characters
32-
sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c
32+
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
3333
url: "https://pub.dev"
3434
source: hosted
35-
version: "1.2.1"
35+
version: "1.3.0"
3636
clock:
3737
dependency: transitive
3838
description:
@@ -45,10 +45,10 @@ packages:
4545
dependency: transitive
4646
description:
4747
name: collection
48-
sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0
48+
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
4949
url: "https://pub.dev"
5050
source: hosted
51-
version: "1.17.0"
51+
version: "1.17.1"
5252
cupertino_icons:
5353
dependency: "direct main"
5454
description:
@@ -89,15 +89,15 @@ packages:
8989
path: ".."
9090
relative: true
9191
source: path
92-
version: "1.0.11"
92+
version: "1.0.12"
9393
js:
9494
dependency: transitive
9595
description:
9696
name: js
97-
sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7"
97+
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
9898
url: "https://pub.dev"
9999
source: hosted
100-
version: "0.6.5"
100+
version: "0.6.7"
101101
lints:
102102
dependency: transitive
103103
description:
@@ -110,10 +110,10 @@ packages:
110110
dependency: transitive
111111
description:
112112
name: matcher
113-
sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72"
113+
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
114114
url: "https://pub.dev"
115115
source: hosted
116-
version: "0.12.13"
116+
version: "0.12.15"
117117
material_color_utilities:
118118
dependency: transitive
119119
description:
@@ -126,18 +126,18 @@ packages:
126126
dependency: transitive
127127
description:
128128
name: meta
129-
sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42"
129+
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
130130
url: "https://pub.dev"
131131
source: hosted
132-
version: "1.8.0"
132+
version: "1.9.1"
133133
path:
134134
dependency: transitive
135135
description:
136136
name: path
137-
sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b
137+
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
138138
url: "https://pub.dev"
139139
source: hosted
140-
version: "1.8.2"
140+
version: "1.8.3"
141141
retry:
142142
dependency: "direct main"
143143
description:
@@ -195,10 +195,10 @@ packages:
195195
dependency: transitive
196196
description:
197197
name: test_api
198-
sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206
198+
sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
199199
url: "https://pub.dev"
200200
source: hosted
201-
version: "0.4.16"
201+
version: "0.5.1"
202202
vector_math:
203203
dependency: transitive
204204
description:
@@ -208,4 +208,4 @@ packages:
208208
source: hosted
209209
version: "2.1.4"
210210
sdks:
211-
dart: ">=2.18.2 <3.0.0"
211+
dart: ">=3.0.0-0 <4.0.0"

lib/async_lock.dart

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import 'dart:async';
2+
3+
/// A lock that ensures that only one async function executes at a time.
4+
class AsyncLock<T> {
5+
/// Creates a new [AsyncLock].
6+
AsyncLock(this.function, {this.retainFutureErrors = false});
7+
8+
/// The function to execute.
9+
final Future<T> Function() function;
10+
11+
Completer<T>? _completer;
12+
13+
/// Whether to retain errors or allow reentrancy until the Future completes
14+
/// successfully.
15+
final bool retainFutureErrors;
16+
17+
/// Executes the given [function] and returns the value, but ensures that
18+
/// only one async function executes at a time. The call defaults to a
19+
/// timeout of 5 minutes.
20+
Future<T> execute([Duration timeout = const Duration(minutes: 5)]) async {
21+
try {
22+
if (_completer != null) {
23+
return _completer!.future;
24+
} else {
25+
_completer = Completer<T>();
26+
}
27+
28+
final result = await function().timeout(
29+
timeout,
30+
onTimeout: () {
31+
//On timeout complete with an error
32+
final error = TimeoutException('Timeout of $timeout exceeded.');
33+
_completer!.completeError(error);
34+
if (!retainFutureErrors) {
35+
//Clear the completer/error if we're not hanging on to it
36+
//TODO: verify this happens in all cases
37+
_completer = null;
38+
}
39+
throw error;
40+
},
41+
);
42+
43+
_completer!.complete(result);
44+
return result;
45+
// ignore: avoid_catches_without_on_clauses
46+
} catch (error, stackTrace) {
47+
// coverage:ignore-start
48+
//This is only here for some potential future use cases
49+
if (retainFutureErrors) {
50+
_completer!.completeError(error, stackTrace);
51+
// coverage:ignore-end
52+
} else {
53+
_completer = null;
54+
}
55+
56+
rethrow;
57+
}
58+
}
59+
}

0 commit comments

Comments
 (0)