Compare commits
	
		
			7 Commits
		
	
	
		
			99cc6708c6
			...
			1a1d539e27
		
	
	| Author | SHA1 | Date | 
|---|---|---|
|  | 1a1d539e27 | |
|  | b7583f4db0 | |
|  | 9392325115 | |
|  | a5dd011506 | |
|  | 0b686e86d9 | |
|  | b0daf0db5f | |
|  | 8581f19127 | 
|  | @ -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 | ||||
|  | @ -0,0 +1,28 @@ | |||
| name: Releasing | ||||
| run-name: ${{ gitea.actor }} is building a release releasing 🚀 | ||||
| on: | ||||
|   release: | ||||
|     types: [created] | ||||
| 
 | ||||
| jobs: | ||||
|   release: | ||||
|     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 }} | ||||
|  | @ -1,6 +1,2 @@ | |||
| .idea/ | ||||
| node_modules/ | ||||
| out/ | ||||
| 
 | ||||
| # Random test file... | ||||
| 0 | ||||
| /target | ||||
| /.idea | ||||
|  | @ -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 = "0.1.0" | ||||
| 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" | ||||
|  | @ -0,0 +1,16 @@ | |||
| [package] | ||||
| name = "kr" | ||||
| version = "0.1.0" | ||||
| 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 | ||||
| 
 | ||||
							
								
								
									
										10
									
								
								bin/test.sh
								
								
								
								
							
							
						
						
									
										10
									
								
								bin/test.sh
								
								
								
								
							|  | @ -1,18 +1,18 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| SLEEP=${1:-'10'} | ||||
| EXIT=${2:-'0'} | ||||
| SLEEP=${1:-10} | ||||
| EXIT=${2:-0} | ||||
| 
 | ||||
| echo "Sleeping for $SLEEP seconds..."; | ||||
| 
 | ||||
| sleep $SLEEP; | ||||
| sleep "$SLEEP"; | ||||
| 
 | ||||
| echo "Waking up!"; | ||||
| 
 | ||||
| if [ $EXIT > 0 ]; then | ||||
| if [ "$EXIT" -gt "0" ]; then | ||||
|   >&2 echo "Exiting with error code $EXIT"; | ||||
| else | ||||
|   echo "Exiting with error code $EXIT"; | ||||
| fi | ||||
| 
 | ||||
| exit $EXIT; | ||||
| exit "$EXIT"; | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										30
									
								
								package.json
								
								
								
								
							
							
						
						
									
										30
									
								
								package.json
								
								
								
								
							|  | @ -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" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										123
									
								
								src/index.js
								
								
								
								
							
							
						
						
									
										123
									
								
								src/index.js
								
								
								
								
							|  | @ -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(); | ||||
|  | @ -0,0 +1,132 @@ | |||
| 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 retry: Retry = Retry { | ||||
|         command: arguments.command, | ||||
|         history: Vec::new(), | ||||
|         max_retries: 4, | ||||
|         timespan: SECONDS_IN_A_MINUTE, | ||||
|         restart_delay: arguments.delay, | ||||
|         restart_name: "minute".to_string(), | ||||
|     }; | ||||
| 
 | ||||
|     if arguments.per_minute > 0 { | ||||
|         retry.max_retries = arguments.per_minute; | ||||
|     } else if arguments.per_hour > 0 { | ||||
|         retry.max_retries = arguments.per_hour; | ||||
|         retry.timespan = SECONDS_IN_A_HOUR; | ||||
|         retry.restart_name = "hour".to_string(); | ||||
|     } | ||||
| 
 | ||||
|     run_command(&mut retry) | ||||
| } | ||||
| 
 | ||||
| fn get_now() -> u64 { | ||||
|     return SystemTime::now() | ||||
|         .duration_since(UNIX_EPOCH) | ||||
|         .unwrap() | ||||
|         .as_secs(); | ||||
| } | ||||
| 
 | ||||
| fn push_history(retry: &mut Retry) { | ||||
|     retry.history.push(get_now() + u64::from(retry.timespan)); | ||||
| } | ||||
| 
 | ||||
| fn update_history(retry: &mut Retry) { | ||||
|     let now = get_now(); | ||||
|     let clear_times: Vec<u64> = retry | ||||
|         .history | ||||
|         .iter() | ||||
|         .filter(|&time| time <= &now) | ||||
|         .map(|&time| time) | ||||
|         .collect(); | ||||
| 
 | ||||
|     for time in clear_times { | ||||
|         retry.history.retain(|&h| h != time); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn check_history(retry: &Retry) -> bool { | ||||
|     return retry.history.len().lt(&usize::from(retry.max_retries)) | ||||
| } | ||||
| 
 | ||||
| fn spawn_process(retry: &Retry) -> std::io::Result<Child> { | ||||
|     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); | ||||
| 
 | ||||
|     return command.spawn(); | ||||
| } | ||||
| 
 | ||||
| fn run_command(retry: &mut 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); | ||||
|         push_history(retry); | ||||
|         update_history(retry); | ||||
|         if check_history(retry) { | ||||
|             println!("Restarting..."); | ||||
|             restart(retry); | ||||
|         } else { | ||||
|             print!("The process has crashed more then {} times in the past {}, stop restarting\n", retry.max_retries, retry.restart_name); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn restart(retry: &mut Retry) { | ||||
|     sleep(Duration::from_secs(u64::from(retry.restart_delay))); | ||||
| 
 | ||||
|     run_command(retry); | ||||
| } | ||||
		Loading…
	
		Reference in New Issue