Skip to content

Commit

Permalink
feat: refactor to exception based control flow
Browse files Browse the repository at this point in the history
Working towards simplifying BehaviorState logic.
Explicitly passing BehaviorState into advance* functions
and slowly moving to delete the BehaviorState methods
off of CentralCommand
As a side-effect of this, this incentivizes
greater coverage since early exits
are now exceptions rather than returns via
a sidechannel.
  • Loading branch information
eseidel committed Jul 28, 2023
1 parent 65fea32 commit 356a91b
Show file tree
Hide file tree
Showing 14 changed files with 310 additions and 199 deletions.
42 changes: 32 additions & 10 deletions packages/cli/lib/behavior/advance.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Future<DateTime?> _advanceIdle(
Api api,
CentralCommand centralCommand,
Caches caches,
BehaviorState state,
Ship ship, {
DateTime Function() getNow = defaultGetNow,
}) async {
Expand All @@ -29,6 +30,7 @@ Future<DateTime?> Function(
Api api,
CentralCommand centralCommand,
Caches caches,
BehaviorState state,
Ship ship, {
DateTime Function() getNow,
}) _behaviorFunction(Behavior behavior) {
Expand Down Expand Up @@ -62,7 +64,7 @@ Future<DateTime?> advanceShipBehavior(
Ship ship, {
DateTime Function() getNow = defaultGetNow,
}) async {
final behavior = await centralCommand.loadBehaviorState(ship);
final state = await centralCommand.loadBehaviorState(ship);
final navResult = await continueNavigationIfNeeded(
api,
ship,
Expand All @@ -76,13 +78,33 @@ Future<DateTime?> advanceShipBehavior(
}

// shipDetail(ship, 'Advancing behavior: ${behavior.behavior.name}');
final behaviorFunction = _behaviorFunction(behavior.behavior);
final waitUntil = await behaviorFunction(
api,
centralCommand,
caches,
ship,
getNow: getNow,
);
return waitUntil;
final behaviorFunction = _behaviorFunction(state.behavior);
try {
final waitUntil = await behaviorFunction(
api,
centralCommand,
caches,
state,
ship,
getNow: getNow,
);
return waitUntil;
} on JobException catch (error) {
if (error.disable == DisableBehavior.thisShip) {
centralCommand.disableBehaviorForShip(
ship,
error.message,
error.timeout,
explicitBehavior: error.explicitBehavior,
);
} else {
centralCommand.disableBehaviorForAll(
ship,
error.message,
error.timeout,
explicitBehavior: error.explicitBehavior,
);
}
}
return null;
}
51 changes: 51 additions & 0 deletions packages/cli/lib/behavior/behavior.dart
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,54 @@ class BehaviorState {
};
}
}

/// Disable behavior for this ship or all ships?
enum DisableBehavior {
/// Disable behavior for this ship only.
thisShip,

/// Disable behavior for all ships.
allShips,
}

/// Exception thrown from a Job.
class JobException implements Exception {
/// Create a new job exception.
JobException(
this.message,
this.timeout, {
this.disable = DisableBehavior.thisShip,
this.explicitBehavior,
}) : assert(message.isNotEmpty, 'why must not be empty'),
assert(timeout.inSeconds > 0, 'timeout must be positive');

/// Why did the job error?
final String message;

/// How long should the calling behavior be disabled
final Duration timeout;

/// Should the behavior be disabled for this ship or all ships?
final DisableBehavior disable;

// Was this exception thrown in a behavior other than the current one?
final Behavior? explicitBehavior;

@override
String toString() => message;
}

/// Exception thrown from a Job if the condition is not met.
void jobAssert(bool condition, String message, Duration timeout) {
if (!condition) {
throw JobException(message, const Duration(seconds: 30));
}
}

/// Exception thrown from a Job if the condition is not met.
T assertNotNull<T>(T? value, String message, Duration timeout) {
if (value == null) {
throw JobException(message, timeout);
}
return value;
}
2 changes: 2 additions & 0 deletions packages/cli/lib/behavior/buy_ship.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:cli/behavior/behavior.dart';
import 'package:cli/behavior/central_command.dart';
import 'package:cli/cache/caches.dart';
import 'package:cli/nav/navigation.dart';
Expand All @@ -10,6 +11,7 @@ Future<DateTime?> advanceBuyShip(
Api api,
CentralCommand centralCommand,
Caches caches,
BehaviorState state,
Ship ship, {
DateTime Function() getNow = defaultGetNow,
}) async {
Expand Down
2 changes: 2 additions & 0 deletions packages/cli/lib/behavior/change_mounts.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:cli/behavior/behavior.dart';
import 'package:cli/behavior/central_command.dart';
import 'package:cli/behavior/deliver.dart';
import 'package:cli/cache/caches.dart';
Expand Down Expand Up @@ -31,6 +32,7 @@ Future<DateTime?> advanceChangeMounts(
Api api,
CentralCommand centralCommand,
Caches caches,
BehaviorState state,
Ship ship, {
DateTime Function() getNow = defaultGetNow,
}) async {
Expand Down
Loading

0 comments on commit 356a91b

Please sign in to comment.