From 5ab47ed4bb93401d2128faceb133790ec7cef419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gediminas=20Mila=C5=A1ius?= Date: Wed, 8 Mar 2023 20:48:24 +0200 Subject: [PATCH] async the sync task --- main.py | 14 +++++++++----- package.json | 2 +- src/apiClient.ts | 28 ++++++++++++++++++++++++++-- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/main.py b/main.py index 1075ab6..d079e42 100644 --- a/main.py +++ b/main.py @@ -2,7 +2,6 @@ import logging import os import re -import subprocess from pathlib import Path plugin_dir = Path(os.path.dirname(os.path.realpath(__file__))) @@ -44,6 +43,7 @@ async def _kill_previous_spawn(process: asyncio.subprocess.Process): class Plugin: current_spawn = None + current_sync = None async def spawn(self, backend_type: str): logger.debug("Executing: spawn(%s)", backend_type) @@ -82,9 +82,14 @@ async def get_backend_type(self): async def sync_now(self): logger.debug("Executing: sync_now()") - subprocess.run([rclone_bin, "copy", "--include-from", - cfg_syncpath_file, "/", "backend:decky-cloud-save", "--copy-links"]) + self.current_sync = await asyncio.subprocess.create_subprocess_exec(rclone_bin, *["copy", "--include-from", cfg_syncpath_file, "/", "backend:decky-cloud-save", "--copy-links"]) + async def sync_now_probe(self): + logger.debug("Executing: sync_now_probe()") + if not self.current_sync: + return 0 + + return self.current_sync.returncode # @@ -164,7 +169,6 @@ async def set_config(self, key: str, value: str): # Asyncio-compatible long-running code, executed in a task when the plugin is loaded - async def _main(self): logger.debug("rclone exe path: %s", rclone_bin) logger.debug("rclone cfg path: %s", rclone_cfg) @@ -179,4 +183,4 @@ async def _main(self): # Function called first during the unload process, utilize this to handle your plugin being removed async def _unload(self): - await _kill_previous_spawn(self.current_spawn) # Kills only if exists + await _kill_previous_spawn(self.current_spawn) # Kills only if exists diff --git a/package.json b/package.json index 94f8db0..661afc3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "decky-cloud-save", - "version": "1.1.0", + "version": "1.1.1", "description": "Manage cloud saves for games that do not support it in [current year].", "scripts": { "build": "shx rm -rf dist && rollup -c", diff --git a/src/apiClient.ts b/src/apiClient.ts index e7a8ee5..cb41543 100644 --- a/src/apiClient.ts +++ b/src/apiClient.ts @@ -1,3 +1,4 @@ +import { sleep } from "decky-frontend-lib"; import { getServerApi, setAppState } from "./state"; export async function syncNow(): Promise { @@ -5,9 +6,32 @@ export async function syncNow(): Promise { setAppState("syncing", "true"); await getServerApi().callPluginMethod("sync_now", {}); - setAppState("syncing", "false"); - getServerApi().toaster.toast({ title: "Decky Cloud Save", body: `Sync completed in ${(new Date().getTime() - start.getTime()) / 1000}s.` }); + let exitCode = 0; + while (true) { + const status = await getServerApi().callPluginMethod<{}, number | undefined>("sync_now_probe", {}); + + if (status.success && status.result != null) { + exitCode = status.result; + break; + } + + await sleep(360); + } + + let body; + switch (exitCode) { + case 0: + case 6: + body = `Sync completed in ${(new Date().getTime() - start.getTime()) / 1000}s.`; + break; + default: + body = `Sync failed. Check journalctl for errors.`; + break; + } + + setAppState("syncing", "false"); + getServerApi().toaster.toast({ title: "Decky Cloud Save", body }); } export async function getCloudBackend(): Promise {