integrate exiting state into state machine

pull/2/head
fuwa 5 years ago
parent 1331c36ac6
commit 628cfa07b6

@ -80,5 +80,5 @@ Stream<String> runBinary (String name, {Stream<String> input}) async* {
// the app should never reach here
log.info('Daemon exited gracefully.');
exit(0);
// exit(0);
}

@ -131,13 +131,24 @@ class _CyberWOW_PageState extends State<CyberWOW_Page> with WidgetsBindingObserv
SyncingState _syncingState = await _loadingState.next(loading, '');
final syncing = process.runBinary(binName, input: inputStreamController.stream).asBroadcastStream();
final syncing = process
.runBinary(binName, input: inputStreamController.stream)
.asBroadcastStream();
SyncedState _syncedState = await _syncingState.next(inputStreamController.sink, syncing, _isExiting);
await _syncedState.next();
HookedState _syncedNextState = await _syncingState.next(inputStreamController.sink, syncing);
var validState = true;
var exited = false;
if (_syncedNextState is SyncedState) {
SyncedState _syncedState = _syncedNextState;
await _syncedState.next();
} else {
ExitingState _exitingState = _syncedNextState;
await _exitingState.wait();
exited = true;
}
var validState = true;
while (validState && !exited) {
await _getState().use
(
@ -148,12 +159,18 @@ class _CyberWOW_PageState extends State<CyberWOW_Page> with WidgetsBindingObserv
(s) => s.next(),
(s) {
s.wait();
log.finer('exit state wait done');
exited = true;
}
);
}
if (!exited) {
log.finer('state machine finished');
if (exited) {
log.finer('popping navigator');
SystemNavigator.pop();
} else {
log.severe('Reached invalid state!');
exit(1);
}
@ -168,7 +185,7 @@ class _CyberWOW_PageState extends State<CyberWOW_Page> with WidgetsBindingObserv
SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);
BlankState _blankState = BlankState(_setState, _getNotification);
BlankState _blankState = BlankState(_setState, _getNotification, _isExiting);
_state = _blankState;
buildStateMachine(_blankState);

@ -72,11 +72,13 @@ abstract class AppState {
typedef SetStateFunc = void Function(AppState);
typedef GetNotificationFunc = AppLifecycleState Function();
typedef IsExitingFunc = bool Function();
class HookedState extends AppState {
final SetStateFunc setState;
final GetNotificationFunc getNotification;
HookedState(this.setState, this.getNotification);
final IsExitingFunc isExiting;
HookedState(this.setState, this.getNotification, this.isExiting);
syncState() {
setState(this);
@ -89,10 +91,10 @@ class HookedState extends AppState {
}
class BlankState extends HookedState {
BlankState(f, s) : super (f, s);
BlankState(f1, f2, f3) : super (f1, f2, f3);
Future<LoadingState> next(String status) async {
LoadingState _next = LoadingState(setState, getNotification, status);
LoadingState _next = LoadingState(setState, getNotification, isExiting, status);
return moveState(_next);
}
}
@ -101,7 +103,7 @@ class LoadingState extends HookedState {
String banner;
String status = '';
LoadingState(f, s, this.banner) : super (f, s);
LoadingState(f1, f2, f3, this.banner) : super (f1, f2, f3);
void append(String msg) {
this.status += msg;
@ -141,7 +143,7 @@ class LoadingState extends HookedState {
await Future.wait([load(), showBanner()]);
}
SyncingState _next = SyncingState(setState, getNotification);
SyncingState _next = SyncingState(setState, getNotification, isExiting);
return moveState(_next);
}
}
@ -150,7 +152,7 @@ class SyncingState extends HookedState {
Queue<String> stdout = Queue();
bool synced = false;
SyncingState(f, s) : super (f, s);
SyncingState(f1, f2, f3) : super (f1, f2, f3);
void append(String msg) {
stdout.addLast(msg);
@ -160,9 +162,9 @@ class SyncingState extends HookedState {
syncState();
}
Future<SyncedState> next
Future<HookedState> next
(
StreamSink<String> processInput, Stream<String> processOutput, IsExitingFunc isExiting
StreamSink<String> processInput, Stream<String> processOutput
) async {
log.fine("Syncing next");
@ -180,6 +182,11 @@ class SyncingState extends HookedState {
await for (final _null in refresh.pull(getNotification, 'syncingState')) {
log.finer('SyncingState: checkSync loop');
if (isExiting()) {
log.fine('Syncing state detected exiting');
break;
}
// here doc is wrong, targetHeight could match height when synced
// potential bug, targetHeight could be smaller then height
final _isConnected = await daemon.isConnected();
@ -195,6 +202,14 @@ class SyncingState extends HookedState {
printStdout();
await checkSync();
if (isExiting()) {
ExitingState _next = ExitingState
(
setState, getNotification, isExiting, stdout, processOutput
);
return moveState(_next);
}
log.fine('syncing: loop exit');
// processInput.add('exit');
@ -206,8 +221,6 @@ class SyncingState extends HookedState {
}
}
typedef IsExitingFunc = bool Function();
class SyncedState extends HookedState {
Queue<String> stdout;
int height;
@ -219,16 +232,15 @@ class SyncedState extends HookedState {
String syncInfo = 'syncInfo';
List<dynamic> getConnections = [];
List<dynamic> getTransactionPool = [];
final IsExitingFunc isExiting;
SyncedState(f, s, this.isExiting, this.stdout, this.processInput, this.processOutput) : super (f, s);
SyncedState(f1, f2, f3, this.stdout, this.processInput, this.processOutput) : super (f1, f2, f3);
void appendInput(String line) {
stdout.addLast('> ' + line + '\n');
processInput.add(line);
}
Future<ReSyncingState> next() async {
Future<HookedState> next() async {
log.fine("Synced next");
Future<void> logStdout() async {
@ -247,12 +259,7 @@ class SyncedState extends HookedState {
await for (final _null in refresh.pull(getNotification, 'syncedState')) {
if (isExiting()) {
log.fine('Synced state detected exiting');
ExitingState _next = ExitingState
(
setState, getNotification, stdout, processOutput
);
return moveState(_next);
break;
}
if (await daemon.isNotSynced()) {
@ -278,6 +285,14 @@ class SyncedState extends HookedState {
await checkSync();
if (isExiting()) {
ExitingState _next = ExitingState
(
setState, getNotification, isExiting, stdout, processOutput
);
return moveState(_next);
}
log.fine('synced: loop exit');
ReSyncingState _next = ReSyncingState
@ -294,9 +309,8 @@ class ReSyncingState extends HookedState {
StreamSink<String> processInput;
Stream<String> processOutput;
bool synced = false;
final IsExitingFunc isExiting;
ReSyncingState(f, s, this.isExiting, this.stdout, this.processInput, this.processOutput) : super (f, s);
ReSyncingState(f1, f2, f3, this.stdout, this.processInput, this.processOutput) : super (f1, f2, f3);
void append(String msg) {
stdout.addLast(msg);
@ -306,7 +320,7 @@ class ReSyncingState extends HookedState {
syncState();
}
Future<SyncedState> next() async {
Future<HookedState> next() async {
log.fine("ReSyncing next");
Future<void> printStdout() async {
@ -320,6 +334,10 @@ class ReSyncingState extends HookedState {
Future<void> checkSync() async {
await for (final _null in refresh.pull(getNotification, 'ReSyncingState')) {
if (isExiting()) {
log.fine('ReSyncing state detected exiting');
break;
}
if (await daemon.isSynced()) {
synced = true;
@ -332,6 +350,14 @@ class ReSyncingState extends HookedState {
printStdout();
await checkSync();
if (isExiting()) {
ExitingState _next = ExitingState
(
setState, getNotification, isExiting, stdout, processOutput
);
return moveState(_next);
}
log.fine('resync: await exit');
SyncedState _next = SyncedState
(
@ -346,7 +372,7 @@ class ExitingState extends HookedState {
Queue<String> stdout;
Stream<String> processOutput;
ExitingState(f, s, this.stdout, this.processOutput) : super (f, s);
ExitingState(f1, f2, f3, this.stdout, this.processOutput) : super (f1, f2, f3);
void append(String msg) {
stdout.addLast(msg);
@ -361,7 +387,7 @@ class ExitingState extends HookedState {
Future<void> printStdout() async {
await for (final line in processOutput) {
log.finest('exiting: print stdout loop');
log.info('exiting: print stdout loop');
append(line);
log.info(line);
@ -369,5 +395,7 @@ class ExitingState extends HookedState {
}
await printStdout();
log.info('exiting state done');
}
}