Skip to content

Commit

Permalink
app: start mainchain on init if not running
Browse files Browse the repository at this point in the history
  • Loading branch information
torkelrogstad committed Nov 13, 2023
1 parent 0e95965 commit e19673b
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 6 deletions.
115 changes: 109 additions & 6 deletions lib/app.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:sail_ui/sail_ui.dart';
import 'package:sail_ui/theme/theme.dart';
import 'package:sail_ui/theme/theme_data.dart';
import 'package:sail_ui/widgets/core/sail_text.dart';
import 'package:sail_ui/widgets/core/scaffold.dart';
import 'package:sail_ui/widgets/loading_indicator.dart';
import 'package:sidesail/logger.dart';
import 'package:sidesail/providers/proc_provider.dart';
import 'package:sidesail/routing/router.dart';
import 'package:sidesail/rpc/rpc_mainchain.dart';
import 'package:sidesail/rpc/rpc_sidechain.dart';
import 'package:sidesail/storage/client_settings.dart';
import 'package:sidesail/storage/sail_settings/theme_settings.dart';
Expand Down Expand Up @@ -34,16 +42,24 @@ class SailApp extends StatefulWidget {
}

class SailAppState extends State<SailApp> with WidgetsBindingObserver {
SailThemeData? theme;
AppRouter get router => GetIt.I.get<AppRouter>();
SidechainRPC get _sidechain => GetIt.I.get<SidechainRPC>();
MainchainRPC get mainchain => GetIt.I.get<MainchainRPC>();
ProcessProvider get processes => GetIt.I.get<ProcessProvider>();
final settings = GetIt.I.get<ClientSettings>();

/// Unrecoverable error on startup we can't get past.
dynamic _initBinariesError;
String mainchainStartupMessage = "Checking if 'drivechaind' is started";
bool binariesStarted = false;
SailThemeData? theme;

@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
loadTheme();
unawaited(loadTheme());
unawaited(initBinaries());
}

void rebuildUI() {
Expand All @@ -64,7 +80,63 @@ class SailAppState extends State<SailApp> with WidgetsBindingObserver {
}
}

void loadTheme([SailThemeValues? themeToLoad]) async {
Future<void> initBinaries() async {
log.d('init binaries: checking mainchain connection');

// First, let the mainchain connection check finish.
await mainchain.initDone;

// If we managed to connect, we're finished here!
if (mainchain.connected) {
log.d('init binaries: mainchain is already running, not doing anything');
setState(() {
binariesStarted = true;
});
return;
}

// We have to start the mainchain
final tempDir = await Directory.systemTemp.createTemp('drivechaind');
final tempLogFile = await File('${tempDir.path}/drivechaind.debug.log').create(recursive: true);

if (!context.mounted) {
return;
}

final args = [
'-debuglogfile=${tempLogFile.path}',
'-regtest',
];

log.d('init binaries: starting drivechaind $args');

try {
final pid = await processes.start(context, 'drivechaind', args);
log.d('init binaries: started drivechaind with PID $pid');
setState(() {
mainchainStartupMessage = "Started 'drivechaind', waiting for successful RPC connection";
});
} catch (err) {
log.w('init binaries: unable to start drivechaind', error: err);
return setState(() {
_initBinariesError = err;
});
}

// Add timeout?
log.i('init binaries: waiting for mainchain connection');
await waitForBoolToBeTrue(() async {
final (connected, _) = await mainchain.testConnection();
return connected;
});

log.i('init binaries: mainchain connected');
return setState(() {
binariesStarted = true;
});
}

Future<void> loadTheme([SailThemeValues? themeToLoad]) async {
themeToLoad ??= (await settings.getValue(ThemeSetting())).value;
if (themeToLoad == SailThemeValues.platform) {
// ignore: deprecated_member_use
Expand All @@ -79,17 +151,37 @@ class SailAppState extends State<SailApp> with WidgetsBindingObserver {
await settings.setValue(ThemeSetting(newValue: themeToLoad));
}

bool get inInitialSetup => theme == null || !binariesStarted;

Widget loadingIndicator() {
if (!binariesStarted) {
return SailColumn(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
spacing: SailStyleValues.padding25,
children: [
SailText.primary20('Mainchain starting up: $mainchainStartupMessage'),
const SailCircularProgressIndicator(),
],
);
}
return const SailCircularProgressIndicator();
}

@override
Widget build(BuildContext context) {
if (theme == null) {
if (inInitialSetup) {
return MaterialApp(
home: Material(
color: _sidechain.chain.color,
child: SailTheme(
data: SailThemeData.lightTheme(_sidechain.chain.color),
child: const SailScaffold(
child: SailScaffold(
body: Center(
child: SailCircularProgressIndicator(),
// TODO: better error message with troubleshooting tips here
child: _initBinariesError != null
? SailText.primary24('Ran into unrecoverable error on startup: $_initBinariesError')
: loadingIndicator(),
),
),
),
Expand All @@ -109,3 +201,14 @@ class SailAppState extends State<SailApp> with WidgetsBindingObserver {
super.dispose();
}
}

Future<void> waitForBoolToBeTrue(
Future<bool> Function() boolGetter, {
Duration pollInterval = const Duration(milliseconds: 100),
}) async {
bool result = await boolGetter();
if (!result) {
await Future.delayed(pollInterval);
await waitForBoolToBeTrue(boolGetter, pollInterval: pollInterval);
}
}
7 changes: 7 additions & 0 deletions lib/rpc/rpc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ abstract class RPCConnection extends ChangeNotifier {
// ping method that tests whether the connection is successful
// should throw if call is not successful
Future<void> ping();

bool _initDone = false;

Future<void> get initDone => _initDone ? Future.value() : Future.any([]);

Future<(bool, String?)> testConnection() async {
try {
await ping();
Expand All @@ -29,6 +34,8 @@ abstract class RPCConnection extends ChangeNotifier {
_log.e('could not ping: ${error.toString()}!');
connectionError = error.toString();
connected = false;
} finally {
_initDone = true;
}
notifyListeners();

Expand Down

0 comments on commit e19673b

Please sign in to comment.