Compare commits

...

24 Commits

Author SHA1 Message Date
Ian Wijma e3623f4ecc Refactor argument handling in main.rs for increased readability
The argument handling in main.rs has been adjusted to utilize argument destructuring, making the code more readable and organized. Additionally, the unnecessary new lines were removed, and commas were added to the last elements of the 'Arguments' struct to follow Rust norms and increase consistency.
2024-01-06 19:57:04 +11:00
Ian Wijma 806d17328c Update kr package version to 1.0.3
Updated the version number of the kr package in both Cargo.toml and Cargo.lock files from version 1.0.2 to 1.0.3. This was necessary for incorporating new features and fixes from the updated version.
2023-12-02 21:52:49 +11:00
Ian Wijma ef1e2c56c0 Refactor 'Retry' instance creation and modify 'run_command' function
Changed the approach for creating 'Retry' instance in main() to avoid mutation behavior by setting 'max_retries', 'timespan' and 'restart_name' initially. The 'per_minute' and 'per_hour' arguments now directly modify these values. Additionally, the 'run_command' function and related functions were refactored to pass 'Retry' instance by value, not reference and to handle 'retry' history separately for each command execution. These changes were made to improve code readability and maintainability.
2023-12-02 21:52:09 +11:00
Ian Wijma 5c19c27136 Add readme.md file
A new readme.md file is added to provide detailed information about usage of Keep Running application. The readme describes the purpose of the application, how to use it, its default settings, arguments and options. It also provides a use case example for better understanding.
2023-11-23 21:27:15 +11:00
Ian Wijma aad5010257 Update workflow run-name and remove id from 'Compile and release'
The run-name in the Github actions workflow 'release.yaml' was updated for clarity, now indicating that the files are being built for release. An unnecessary id tag was removed from the 'Compile and release' step, simplifying the workflow. This makes the functioning of the workflow easier to understand and manage.
2023-11-21 01:13:08 +11:00
Ian Wijma ffa6d18e5e Update GitHub CI action trigger in release.yaml
Changed the event trigger of the GitHub Actions workflow "release.yaml" from a generic 'release' event to specifically when a 'release' is 'created'. This provides the detailed triggering condition for the workflow, ensuring it only runs when needed, improving workflow optimization.
2023-11-21 01:10:07 +11:00
Ian Wijma 049a75e300 Update version and fix CI action name
Updated kr package's version to 1.0.2 in Cargo.toml and Cargo.lock files. Also, fixed the wrong property reference in the GitHub Actions release workflow. From "gitea.actor" to "github.actor" which might have caused incorrect workflow run name in GitHub CI/CD.
2023-11-21 01:07:37 +11:00
Ian Wijma dcf83a351f Update version and fix CI action name
Updated kr package's version to 1.0.2 in Cargo.toml and Cargo.lock files. Also, fixed the wrong property reference in the GitHub Actions release workflow. From "gitea.actor" to "github.actor" which might have caused incorrect workflow run name in GitHub CI/CD.
2023-11-21 01:03:51 +11:00
Ian Wijma 66ab232c9d Updated .gitignore, Cargo.toml and release.yaml files
This commit adds newline at the end of the .gitignore and release.yaml files to adhere to posix standard while removing unnecessary whitespace in Cargo.toml file. Changes are made for better code health and adhering to standards.
2023-11-21 00:57:18 +11:00
Ian Wijma 99947dbefd Refactor spawn_process fn to handle spawn error
This commit modifies the spawn_process function to explicitly return a Result type, handling the error of the spawn() method. This change improves the readability of the error handling and makes it more idiomatic in Rust. As a secondary correction, it fixes a typo in a print statement.
2023-11-21 00:34:53 +11:00
Ian Wijma df5776e76d Refactor spawn_process fn to handle spawn error
This commit modifies the spawn_process function to explicitly return a Result type, handling the error of the spawn() method. This change improves the readability of the error handling and makes it more idiomatic in Rust. As a secondary correction, it fixes a typo in a print statement.
2023-11-21 00:31:40 +11:00
Ian Wijma 563938e51a Refactor spawn_process fn to handle spawn error
This commit modifies the spawn_process function to explicitly return a Result type, handling the error of the spawn() method. This change improves the readability of the error handling and makes it more idiomatic in Rust. As a secondary correction, it fixes a typo in a print statement.
2023-11-21 00:31:37 +11:00
Ian Wijma 8e6950270e Simplify workflow trigger for releases
Refactored the workflow trigger for releases in 'release.yaml' to directly listen to release events. The change simplifies the code and aligns with the syntax used in other parts of the workflow. It was necessary for maintaining consistency and cleanliness of the workflows codebase.
2023-11-21 00:21:06 +11:00
Ian Wijma d2f72f4ad7 Upgrade kr package to version 1.0.0.
In this commit, we've updated the kr package from version 0.1.0 to 1.0.0 in the Cargo.toml file, signifying a milestone update recognizing the project's stability and maturity.
2023-11-21 00:13:22 +11:00
Ian Wijma 45925b56f1 Merge remote-tracking branch 'origin/main' 2023-11-21 00:12:43 +11:00
Ian Wijma 20bfc647af Update kr package version in Cargo.toml
The kr package version was updated from 0.1.0 to 1.0.0 in the Cargo.toml file. This change indicates that the project has reached a significant milestone and is now considered mature and stable enough for a major version release.
2023-11-21 00:12:35 +11:00
Ian Wijma 250bc93b2d Update kr package version in Cargo.toml
The kr package version was updated from 0.1.0 to 1.0.0 in the Cargo.toml file. This change indicates that the project has reached a significant milestone and is now considered mature and stable enough for a major version release.
2023-11-21 00:11:56 +11:00
Ian Wijma 1a1d539e27 Merge pull request 'topic/rust' (#2) from topic/rust into main
Reviewed-on: #2
2023-11-20 13:10:23 +00:00
Ian Wijma b7583f4db0 Update Cargo.toml for optimized release binary
Configured the `Cargo.toml` to automatically strip symbols, optimize for size, enable Link Time Optimization (LTO), and set codegen-units to 1 for the release profile. This significantly reduces the size and improves the performance of the resulting binary.
2023-11-21 00:08:17 +11:00
Ian Wijma 9392325115 Correct commit message for the given diff:
Add newline character to error message

In this commit, a newline character `\n` was added at the end of the error message in the `print!` function within main.rs. This change ensures the output from the program is properly formatted and readable, increasing the overall user experience when such exceptions are encountered.
2023-11-21 00:08:03 +11:00
Ian Wijma a5dd011506 Renamed workflow and adjusted it to handle releases
In this commit, I've renamed the name of the workflow from build.yaml to release.yaml. It now gets triggered on 'release' instead of 'push'. The job names and some parameters were also altered to fit into the new release context. The aim of this modification is to optimize the project delivery process as the workflow is now focus on handling final product releases.
2023-11-21 00:00:05 +11:00
Ian Wijma 0b686e86d9 Update build.yaml to streamline compilation and packaging process
Keep Running / Build (tar.gz tar.xz tar.zst, x86_64-unknown-linux-musl) (push) Successful in 1m54s Details
Keep Running / Build (zip, x86_64-apple-darwin) (push) Successful in 1m9s Details
Keep Running / Build (zip, x86_64-pc-windows-gnu) (push) Successful in 1m9s Details
This commit simplifies and optimizes the build workflow process by leveraging the rust-build action for compiling and releasing. The "build.yaml" file has been revised to include different targets and types of archives as per the platform. Also, previous separate jobs for checking out, installing dependencies, building project, and creating/uploading archives have been removed. The new strategy is aimed to reduce redundancy, speed up the process, and allow seamless multi-platform build support.
2023-11-20 23:47:04 +11:00
Ian Wijma b0daf0db5f Improve script safety by quoting variables and updating comparisons
This commit updates the `test.sh` script to incorporate best shell scripting practices. Changes include quoting the variables "$SLEEP" and "$EXIT" to handle null or space-containing values better. The arithmetic comparison has been updated to use "bash-style" to improve the script's security. This refactoring aims to enhance the overall efficiency and reliability of the script execution.
2023-11-20 23:40:56 +11:00
Ian Wijma 8581f19127 Remove outdated codebase
This commit deletes the current codebase and configurations because we're switching to rust. This includes src/index.js, package.json, package-lock.json and .gitignore files. A refactor or rewrite app with updated dependencies and code style will be added afterwards.
2023-11-20 23:40:22 +11:00
12 changed files with 529 additions and 1650 deletions

View File

@ -1,42 +0,0 @@
name: Keep Running
run-name: ${{ gitea.actor }} is running spotify.local CI pipeline 🚀
on: [push]
concurrency: 'true'
jobs:
Build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install dependencies
run: npm ci
- name: Building project
run: npm run build
- name: Creating Linux Archive
uses: vimtor/action-zip@v1.1
with:
files: out/kr-linux
dest: linux.zip
- name: Upload Linux Archive
uses: actions/upload-artifact@v3
with:
path: linux.zip
- name: Creating MacOS Archive
uses: vimtor/action-zip@v1.1
with:
files: out/kr-macos
dest: macos.zip
- name: Upload MacOS Archive
uses: actions/upload-artifact@v3
with:
path: macos.zip
- name: Creating Windows Archive
uses: vimtor/action-zip@v1.1
with:
files: out/kr-win.exe
dest: windows.zip
- name: Upload Windows Archive
uses: actions/upload-artifact@v3
with:
path: windows.zip

29
.github/workflows/release.yaml vendored Normal file
View File

@ -0,0 +1,29 @@
name: Releasing
run-name: ${{ github.actor }} is building the files for a release 🚀
on:
release:
types: [created]
jobs:
release:
name: release ${{ matrix.target }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-pc-windows-gnu
archive: zip
- target: x86_64-unknown-linux-musl
archive: tar.gz tar.xz tar.zst
- target: x86_64-apple-darwin
archive: zip
steps:
- uses: actions/checkout@master
- name: Compile and release
uses: rust-build/rust-build.action@v1.4.4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
RUSTTARGET: ${{ matrix.target }}
ARCHIVE_TYPES: ${{ matrix.archive }}

8
.gitignore vendored
View File

@ -1,6 +1,2 @@
.idea/ /target
node_modules/ /.idea
out/
# Random test file...
0

298
Cargo.lock generated Normal file
View File

@ -0,0 +1,298 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "anstream"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
[[package]]
name = "anstyle-parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"
dependencies = [
"anstyle",
"windows-sys",
]
[[package]]
name = "bitflags"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
[[package]]
name = "clap"
version = "4.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
"terminal_size",
"unicase",
"unicode-width",
]
[[package]]
name = "clap_derive"
version = "4.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
[[package]]
name = "colorchoice"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "errno"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "kr"
version = "1.0.3"
dependencies = [
"clap",
]
[[package]]
name = "libc"
version = "0.2.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
[[package]]
name = "linux-raw-sys"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829"
[[package]]
name = "proc-macro2"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustix"
version = "0.38.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "2.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "terminal_size"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7"
dependencies = [
"rustix",
"windows-sys",
]
[[package]]
name = "unicase"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
dependencies = [
"version_check",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-width"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"

15
Cargo.toml Normal file
View File

@ -0,0 +1,15 @@
[package]
name = "kr"
version = "1.0.3"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
clap = { version = "4.4.8", features = ["derive", "unicode", "wrap_help"] }
[profile.release]
strip = true # Automatically strip symbols from the binary.
opt-level = "z" # Optimize for size.
lto = true
codegen-units = 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

View File

@ -1,18 +1,18 @@
#!/bin/bash #!/bin/bash
SLEEP=${1:-'10'} SLEEP=${1:-10}
EXIT=${2:-'0'} EXIT=${2:-0}
echo "Sleeping for $SLEEP seconds..."; echo "Sleeping for $SLEEP seconds...";
sleep $SLEEP; sleep "$SLEEP";
echo "Waking up!"; echo "Waking up!";
if [ $EXIT > 0 ]; then if [ "$EXIT" -gt "0" ]; then
>&2 echo "Exiting with error code $EXIT"; >&2 echo "Exiting with error code $EXIT";
else else
echo "Exiting with error code $EXIT"; echo "Exiting with error code $EXIT";
fi fi
exit $EXIT; exit "$EXIT";

1444
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,30 +0,0 @@
{
"name": "kr",
"version": "1.0.0",
"description": "",
"bin": "src/index.js",
"main": "src/index.js",
"scripts": {
"build": "pkg package.json",
"copy-local": "cp -f out/kr-linux ~/bin/kr",
"build-local": "npm run build && npm run copy-local"
},
"pkg": {
"scripts": "src/**/*.js",
"targets": [
"node18-linux-x64",
"node18-macos-x64",
"node18-win-x64"
],
"outputPath": "out"
},
"author": "Ian Wijma",
"dependencies": {
"pkg": "^5.8.1",
"yargs": "^17.7.2"
},
"devDependencies": {
"@types/node": "^20.8.10",
"@types/yargs": "^17.0.29"
}
}

35
readme.md Normal file
View File

@ -0,0 +1,35 @@
Keep Running
---
Keep running is a quick and easy way to **keep** a process **running** during development or other **non-production** tasks.
> Please for the love of sanity, do not use this is production...
# Usage
Below you will see the output of the `--help` command.
Do note that if you don't specify any `--per-*` flag, it defaults to `--per-minute=4`.
```
Usage: kr [OPTIONS] <COMMAND>
Arguments:
<COMMAND>
Options:
--per-minute <PER_MINUTE> [default: 0]
--per-hour <PER_HOUR> [default: 0]
--delay <DELAY> [default: 0]
-h, --help Print help
-V, --version Print version
```
# Use cases
## Game servers
/keep-running/ is a great tool to run, for example, a Modded minecraft server.
As it automatically restarts the server if a crash occurs.
![img.png](assets/vault-hunters-3rd.png)

View File

@ -1,123 +0,0 @@
const Yargs = require('yargs');
const {spawn} = require("child_process");
const yargs = Yargs(process.argv.splice(2))
.scriptName('kr')
.usage('kr [args] <process-to-run>')
.help()
.option('_rpm', {
default: 0,
description: 'The amount of Retries Per Minute, before we stop retrying',
type: 'number'
})
.option('_rph', {
default: 0,
description: 'The amount of Retries Per Hour, before we stop retrying',
type: 'number'
})
.option('_delay', {
default: 0,
description: 'Time in seconds we want to delay the restart with.',
type: 'number'
})
const { _ = [], _rpm: rpm, _rph: rph, _delay: delay } = yargs.argv;
const [command, ...args ] = _;
if (!command) {
return yargs.showHelp();
}
const SECONDS_IN_A_MINUTE = 60;
const SECONDS_IN_A_HOUR = 60 * 60;
let historyMax = 4;
let seconds = SECONDS_IN_A_MINUTE;
let restartName = 'minute';
if (rpm && rph) {
return console.error('Currently, can not define both --rpm and --rph, please choose only one.');
} else if (rpm) {
historyMax = rpm
} else if (rph) {
historyMax = rph
seconds = SECONDS_IN_A_HOUR
restartName = 'hour'
}
/** @type {Object<number, string>} */
const history = {};
const getNow = () => Math.ceil(Date.now() / 1000); // Time in seconds
/** @param {string} logs */
const pushHistory = (logs) => history[getNow() + seconds] = logs;
const updateHistory = () => {
const now = getNow();
const clearKeys = Object.keys(history)
.filter((time) => time <= now);
clearKeys.forEach((key) => delete history[key]);
}
const checkHistory = () => Object.keys(history).length <= historyMax;
const restart = () => setTimeout(() => runCommand(delay), delay * 1000);
const spawnCommand = () => {
const [ spawnCommand, ...cmdArgs ] = command.split(' ');
const spawnArgs = [...cmdArgs, ...args];
return spawn(spawnCommand, spawnArgs);
}
const runCommand = () => {
const runner = spawnCommand();
const commandLogs = [];
const pushLog = (logEntry) => commandLogs.push(logEntry);
const trimLog = () => {
if(commandLogs.length > 5000) commandLogs.shift()
};
const clearLogs = () => commandLogs.length = 0;
const getLogs = () => commandLogs.join('\n');
const handleOut = (type, message) => {
pushLog(`[${type}]\t${message}`);
trimLog();
};
const handleExit = (exitCode) => {
if (exitCode === 0) {
console.log(`Exit code: ${exitCode}`);
} else{
console.log(`[CRASH] exit code: ${exitCode}`)
pushHistory(getLogs());
clearLogs();
updateHistory();
if (checkHistory()) {
console.log('Restarting...');
restart();
} else {
console.error(`The process crashed more then ${historyMax} times in the past ${restartName}, stop retrying.`);
console.error(`See below the last crash log:`);
const keys = Object.keys(history);
const lastKey = keys[keys.length-1];
console.log(history[lastKey]);
}
}
}
runner.on('close', (exitCode) => handleExit(exitCode))
runner.stdout.on('data', (data) => console.log(data.toString().trim()))
runner.stdout.on('data', (data) => handleOut('LOG', data.toString().trim()))
runner.stderr.on('data', (data) => handleOut('ERR', data.toString().trim()))
}
// Leggo!~
runCommand();

145
src/main.rs Normal file
View File

@ -0,0 +1,145 @@
use std::process::{Child, Command};
use std::thread::sleep;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use clap::{arg, Parser};
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Arguments {
// The amount of times we retry in a span of a minute, before we stop retrying
#[arg(long, default_value_t = 0, conflicts_with = "per_hour")]
per_minute: u8,
// The amount of times we retry in a span of a hour, before we stop retrying
#[arg(long, default_value_t = 0, conflicts_with = "per_minute")]
per_hour: u8,
// The amount of seconds we want to delay the restart with.
#[arg(long, default_value_t = 0)]
delay: u8,
#[arg()]
command: String,
}
const SECONDS_IN_A_MINUTE: u16 = 60;
const SECONDS_IN_A_HOUR: u16 = 60 * 60;
struct Retry {
command: String,
history: Vec<u64>,
max_retries: u8,
timespan: u16,
restart_delay: u8,
restart_name: String,
}
fn main() {
let arguments = Arguments::parse();
let mut max_retries = 4;
let mut timespan = SECONDS_IN_A_MINUTE;
let mut restart_name = String::from("minute");
let Arguments { per_minute, per_hour, .. } = arguments;
if per_minute > 0 {
max_retries = per_minute;
} else if per_hour > 0 {
max_retries = per_hour;
timespan = SECONDS_IN_A_HOUR;
restart_name = String::from("hour");
}
let Arguments { command, delay: restart_delay, .. } = arguments;
let retry: Retry = Retry {
max_retries,
timespan,
restart_name,
command,
restart_delay,
history: Vec::new(),
};
run_command(retry)
}
fn get_now() -> u64 {
return SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs();
}
fn push_history(mut history: Vec<u64>, timespan: u16) -> Vec<u64> {
history.push(get_now() + u64::from(timespan));
return history.to_owned()
}
fn update_history(mut history: Vec<u64>) -> Vec<u64> {
let now = get_now();
let clear_times: Vec<u64> = history
.iter()
.filter(|&time| time <= &now)
.map(|&time| time)
.collect();
for time in clear_times {
history.retain(|&h| h != time);
}
return history.to_owned();
}
fn check_history(history: &Vec<u64>, max_retries: u8) -> bool {
return history.len().lt(&usize::from(max_retries))
}
fn spawn_process(retry: &Retry) -> Result<Child, std::io::Error> {
let mut command_parts: Vec<String> = retry
.command
.split_whitespace()
.map(|s| s.to_string())
.collect();
let mut command: Command = Command::new(&command_parts[0]);
command_parts.remove(0);
command.args(command_parts);
match command.spawn() {
Ok(child) => Ok(child),
Err(err) => Err(err),
}
}
fn run_command(mut retry: Retry) {
let mut process = spawn_process(&retry)
.expect("Process failed on startup");
let exit_code = match process.wait() {
Ok(exit_code) => exit_code,
Err(err) => {
eprintln!("Failed to wait for process: {}", err);
return;
}
};
if exit_code.success() {
println!("Exit code: {}", exit_code);
} else {
println!("[CRASH] exit code: {}", exit_code);
let pushed_history = push_history(retry.history, retry.timespan);
let updated_history = update_history(pushed_history);
if check_history(&updated_history, retry.max_retries) {
retry.history = updated_history;
println!("Restarting...");
restart(retry);
} else {
println!("The process has crashed more than {} times in the past {}, stop restarting\n", retry.max_retries, retry.restart_name);
}
}
}
fn restart(retry: Retry) {
sleep(Duration::from_secs(u64::from(retry.restart_delay)));
run_command(retry);
}