Skip to content

Commit

Permalink
providers: add process management
Browse files Browse the repository at this point in the history
  • Loading branch information
torkelrogstad committed Nov 13, 2023
1 parent d8fc04e commit 0e95965
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 4 deletions.
4 changes: 4 additions & 0 deletions lib/config/dependencies.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:get_it/get_it.dart';
import 'package:sidesail/config/sidechains.dart';
import 'package:sidesail/providers/balance_provider.dart';
import 'package:sidesail/providers/proc_provider.dart';
import 'package:sidesail/providers/transactions_provider.dart';
import 'package:sidesail/routing/router.dart';
import 'package:sidesail/rpc/rpc_ethereum.dart';
Expand Down Expand Up @@ -34,6 +35,9 @@ Future<void> initGetitDependencies(Sidechain initialChain) async {
// we start polling for balance updates
() => BalanceProvider(),
);

GetIt.I.registerLazySingleton(() => ProcessProvider());

GetIt.I.registerLazySingleton<TransactionsProvider>(
() => TransactionsProvider(),
);
Expand Down
94 changes: 94 additions & 0 deletions lib/providers/proc_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:logger/logger.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sidesail/logger.dart';

class ProcessProvider extends ChangeNotifier {
ProcessProvider();

// List of currently running processes.
List<int> pids = [];

final Map<int, int> _exitCodes = {};
final List<int> _runningProcesses = [];

final Map<int, Stream<String>> _stdoutStreams = {};
final Map<int, Stream<String>> _stderrStreams = {};

Stream<String> stdout(int pid) => _stdoutStreams[pid] ?? const Stream.empty();
Stream<String> stderr(int pid) => _stderrStreams[pid] ?? const Stream.empty();
bool running(int pid) => _runningProcesses.contains(pid);

// Starts a binary located in the asset bundle included with the app.
Future<int> start(BuildContext context, String binary, List<String> args) async {
// TODO: lookup based on arch + platform
final binResource = await DefaultAssetBundle.of(context).load('assets/bin/$binary');

final temp = await getTemporaryDirectory();

final file = File('${temp.path}/$binary');

// Have to convert the ByteData -> List<int>. Side note: why tf does writeAsBytes
// operate on a list of numbers? Jesus
// https://stackoverflow.com/a/50121777
final buffer = binResource.buffer;
await file.writeAsBytes(
buffer.asUint8List(binResource.offsetInBytes, binResource.lengthInBytes),
);

// Must be executable before we can start.
// TODO: what to do on Windows here
await Process.run('chmod', ['+x', file.path]);

final process = await Process.start(
file.path,
args,
mode: ProcessStartMode.normal, // when the flutter app quits, this process quit
);
log.d('started "$binary" with pid ${process.pid}');
_runningProcesses.add(process.pid);

// Let output streaming chug in the background

// Proper logs are written here
_stdoutStreams[process.pid] = process.stdout.transform(utf8.decoder);

// Error messages while starting up are written here
_stderrStreams[process.pid] = process.stderr.transform(utf8.decoder);

// Register a handler for when the process stops.
unawaited(
process.exitCode.then((code) async {
var level = Level.error;
// Node software exited with a success code. Someone called
// `drivechain-cli stop`?
if (code == 0) {
level = Level.info;
}

final errLogs = await (_stderrStreams[process.pid] ?? const Stream.empty()).toList();
log.log(level, '"$binary" exited with code $code: $errLogs');

// Forward to listeners that the process finished.
_exitCodes[process.pid] = code;
_runningProcesses.remove(process.pid);
notifyListeners();
}),
);

notifyListeners();
return process.pid;
}

@override
void dispose() {
super.dispose();

log.d('dispose process provider: killing processes $_runningProcesses');
_runningProcesses.forEach(Process.killPid);
}
}
2 changes: 1 addition & 1 deletion pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ packages:
source: hosted
version: "1.0.1"
path_provider:
dependency: transitive
dependency: "direct main"
description:
name: path_provider
sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
Expand Down
9 changes: 6 additions & 3 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,15 @@ dependencies:
collection: ^1.17.2
stacked: ^3.4.1+1
intl: ^0.18.0
web3dart:
web3dart:
git:
url: https://github.com/xclud/web3dart.git
ref: main
http: ^1.1.0
path_provider: ^2.1.1

# Needed for silencing complaints from adding the web3dart lib
dependency_overrides:
dependency_overrides:
stream_channel: 2.1.2

dev_dependencies:
Expand All @@ -85,6 +85,9 @@ flutter:
# the material Icons class.
uses-material-design: true

assets:
- assets/bin/

fonts:
- family: SourceCodePro
fonts:
Expand Down

0 comments on commit 0e95965

Please sign in to comment.