-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Handle multiple network endpoints and choose a healthy one with offch…
…ain indexing enabled (#1693) * add simple `EndpointManager` class * [EndpointManager] minor fixes * [EndpointManager] Extract EndpointChecker * [EndpointManager] fmt * [EndpointManager] fix: change abstract class to mixin * minor fixes * [config/networks] add endpoints and rename them * [api] use `EndpointManager` in API * [api] check for offchain indexing in the healthcheck * [dart_api] proper condition of offchain indexing enablement log. * [dart_api] remove unused code * [EndpointManager] randomize order of healthcheck. * [const/network] better naming convention for address field * [EndpointManager] make randomization optional * fmt * update pubspec_overrides.yaml
- Loading branch information
Showing
12 changed files
with
589 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
include: package:very_good_analysis/analysis_options.3.1.0.yaml | ||
|
||
linter: | ||
rules: | ||
public_member_api_docs: false | ||
lines_longer_than_80_chars: false | ||
sort_pub_dependencies: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import 'dart:math'; | ||
|
||
mixin Endpoint { | ||
String address(); | ||
} | ||
|
||
mixin EndpointChecker<E extends Endpoint> { | ||
Future<bool> checkHealth(E endpoint); | ||
} | ||
|
||
class EndpointManager<C extends EndpointChecker, E extends Endpoint> { | ||
EndpointManager(this._checker); | ||
|
||
EndpointManager.withEndpoints(this._checker, List<E> endpoints) { | ||
for (final e in endpoints) { | ||
this.endpoints[e.address()] = e; | ||
} | ||
} | ||
|
||
Map<String, E> endpoints = {}; | ||
|
||
final EndpointChecker _checker; | ||
|
||
void addEndpoint(E endpoint) { | ||
endpoints[endpoint.address()] = endpoint; | ||
} | ||
|
||
void removeEndpoint(E endpoint) { | ||
endpoints.remove(endpoint.address()); | ||
} | ||
|
||
List<E> getEndpoints() { | ||
return endpoints.values.toList(); | ||
} | ||
|
||
/// Returns the first endpoint that is healthy where the checks are optionally run in random order. | ||
/// | ||
/// Will return null if all endpoints are unhealthy. | ||
Future<E?> getHealthyEndpoint({bool randomize = false}) { | ||
final values = endpoints.values.toList(); | ||
|
||
if (randomize) { | ||
values.shuffle(Random()); | ||
} | ||
|
||
return firstWhereAsync(values, _checker.checkHealth); | ||
} | ||
|
||
/// Returns a future that completes once a healthy endpoint has been found. | ||
Future<E> pollHealthyEndpoint({bool randomize = false}) async { | ||
E? endpoint; | ||
|
||
while ((endpoint = await getHealthyEndpoint(randomize: randomize)) == null) { | ||
await Future<void>.delayed(const Duration(seconds: 5)); | ||
} | ||
|
||
return endpoint!; | ||
} | ||
} | ||
|
||
Future<T?> firstWhereAsync<T>( | ||
Iterable<T> items, | ||
Future<bool> Function(T) test, | ||
) async { | ||
for (final item in items) { | ||
if (await test(item).timeout(const Duration(seconds: 2), onTimeout: () => false)) { | ||
return item; | ||
} | ||
} | ||
return null; | ||
} |
Oops, something went wrong.