Skip to content

Add cleanup procedure for unused Microbot clients#25

Merged
chsami merged 3 commits intochsami:mainfrom
Bolado:feat/clean-unused-jars
Sep 12, 2025
Merged

Add cleanup procedure for unused Microbot clients#25
chsami merged 3 commits intochsami:mainfrom
Bolado:feat/clean-unused-jars

Conversation

@Bolado
Copy link
Copy Markdown
Contributor

@Bolado Bolado commented Sep 11, 2025

Client executables will be tracked based on their most recent launch time. Initially, all existing clients on the user's machine will have their "last launched time" set to the current time. Versions not yet tracked are added to the JSON file with the current time whenever user opens the launcher. Whenever a client .jar is launched, its "last launched time" is updated to the current time. If a client .jar is not launched for three days, it is deleted unless it is the latest available version, which is always retained.

Github Copilot Summary

This pull request introduces a system for tracking and cleaning up unused client JAR files in the microbotDir, ensuring only recently used and the latest client versions are retained. It does this by recording last-used timestamps in a JSON file and providing routines to update and clean up these files, which are integrated into the application's IPC and renderer logic. Additionally, some minor cleanup and version bumping are included.

Client JAR TTL management and cleanup:

  • Added getClientsJarTTL, cleanupUnusedClientsJar, and updateClientJarTTL functions to dir-module.js to track last-used timestamps for each client JAR, delete unused JARs older than 3 days (except the latest), and update usage timestamps.
  • Exposed new IPC handlers in ipc-handlers.js for cleaning up unused client JARs and updating TTL data, allowing renderer processes to trigger these actions.
  • Added cleanUnusedClients and updateClientJarTTL methods to the Electron context bridge in preload.js for renderer access.

Renderer integration:

  • Updated renderer.js to call updateClientJarTTL whenever a client is opened or played, and to trigger cleanUnusedClients on load, logging errors if any occur. [1] [2] [3]

Miscellaneous:

  • Removed unused default properties (launcher, launcher_html) from properties.js for cleanup.
  • Bumped package version to 3.2.3 in package.json.

Summary by CodeRabbit

  • New Features

    • Automatic cleanup of outdated client files (keeps latest) to free disk space; runs in background after config updates and client opens/launches.
    • Background tracking that refreshes last-used timestamps when opening or launching clients.
  • Chores

    • Simplified default settings: newly created config files no longer include unused launcher entries.
    • Version bumped to 3.2.3.

- Implement getClientsJarTTL to manage clients jar TTL data
- Add cleanupUnusedClientsJar to remove old jar files
- Introduce updateClientJarTTL to update last used timestamps
- Integrate IPC handlers for cleanup and update operations
- Expose new functions in preload.js for renderer access
- Update renderer.js to call new functions for jar management
- Remove unused properties from defaultProperties in properties.js
- Bump version in package.json to 3.2.3
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Sep 11, 2025

Walkthrough

Adds TTL tracking and cleanup for microbot client JARs: new functions in libs/dir-module.js to read/update TTL and remove old jars; IPC handlers and preload bridge methods to invoke those functions; renderer calls to refresh TTL and trigger cleanup; removed two default properties and bumped package version.

Changes

Cohort / File(s) Summary of changes
Client JAR TTL & Cleanup Core
libs/dir-module.js
Added getClientsJarTTL(), cleanupUnusedClientsJar(latestVersion), updateClientJarTTL(version); persists TTL to clients_jar_ttl.json; exported new functions alongside microbotDir and openLocation.
IPC Wiring
libs/ipc-handlers.js
Added IPC channels cleanup-unused-clients-jar and update-client-jar-ttl that dynamically require libs/dir-module.js and delegate to the new dir-module functions.
Electron Bridge & Renderer
preload.js, renderer.js
preload.js: exposed cleanUnusedClients(latestVersion) and updateClientJarTTL(version). renderer.js: calls updateClientJarTTL before launches and cleanUnusedClients on load; logs non-blocking errors.
Properties Defaults
libs/properties.js
Removed launcher and launcher_html from defaultProperties; remaining defaults keep client and version_pref.
Versioning
package.json
Bumped package version from 3.2.2 to 3.2.3.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant UI as Renderer (UI)
  participant Preload as Preload Bridge
  participant IPC as Main IPC
  participant Dir as dir-module

  rect rgb(240,248,255)
    note over UI,Dir: TTL refresh when launching a client
    User->>UI: start client (with version)
    UI->>Preload: updateClientJarTTL(version)
    Preload->>IPC: invoke 'update-client-jar-ttl'
    IPC->>Dir: updateClientJarTTL(version)
    Dir-->>IPC: { success / error }
    IPC-->>Preload: result
    Preload-->>UI: result (logged if error)
  end

  rect rgb(245,255,240)
    note over UI,Dir: Cleanup old jars (exclude latest)
    UI->>Preload: cleanUnusedClients(latestVersion)
    Preload->>IPC: invoke 'cleanup-unused-clients-jar'
    IPC->>Dir: cleanupUnusedClientsJar(latestVersion)
    Dir-->>IPC: { success / error }
    IPC-->>Preload: result
    Preload-->>UI: result (logged if error)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • chsami

Pre-merge checks (3 passed)

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "Add cleanup procedure for unused Microbot clients" is concise and directly reflects the PR's primary change—adding TTL tracking and automated cleanup of unused client JARs (implemented in dir-module.js with IPC and renderer/preload hooks)—so it accurately summarizes the main intent without extraneous detail.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

Poem

I hop through jars and mark the time,
I note each version, nudge stale to resign.
Latest stays cozy, old ones I prune—
A tidy burrow, humming like noon.
Carrot cheers for 3.2.3! 🥕🐇


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3cb0f66 and 2d5fbd6.

📒 Files selected for processing (1)
  • libs/dir-module.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • libs/dir-module.js
✨ Finishing touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
libs/ipc-handlers.js (1)

15-16: Broken base URL (missing slash) prevents version fetches.
'https:/microbot.cloud' should be 'https://microbot.cloud'.

Apply this diff:

-    const url = 'https:/microbot.cloud';
+    const url = 'https://microbot.cloud';
🧹 Nitpick comments (8)
libs/dir-module.js (4)

78-101: Initialize TTL file more defensively (encoding + shape guard).
Explicitly set encoding when creating the file and coerce malformed JSON to an object to avoid downstream crashes.

Apply this diff:

-            const data = await fs.readFile(filePath, 'utf8');
-            return { success: true, data: JSON.parse(data) };
+            const data = await fs.readFile(filePath, 'utf8');
+            let parsed = JSON.parse(data);
+            if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
+                parsed = {};
+            }
+            return { success: true, data: parsed };
         } catch (readErr) {
             if (readErr.code === 'ENOENT') {
-                await fs.writeFile(filePath, JSON.stringify({}));
+                await fs.writeFile(filePath, JSON.stringify({}), 'utf8');
                 return { success: true, data: {} };

121-140: Minor nits: hoist now() and tighten version parsing.

  • Use a single const now = Date.now() for the whole function for consistency.
  • Consider extracting version via a regex (e.g., /^microbot-(.+).jar$/) to avoid edge cases.

146-169: Return deletion stats and remove unused variable.
deletedAny is set but unused. Returning a count helps telemetry and debugging.

Apply this diff:

-    let deletedAny = false;
+    let deletedCount = 0;
@@
-                delete ttlData[version];
-                deletedAny = true;
+                delete ttlData[version];
+                deletedCount += 1;
                 updated = true;
@@
-    if (!updated) {
-        return { success: true };
-    }
+    if (!updated) {
+        return { success: true, deleted: 0 };
+    }
@@
-    return { success: true };
+    return { success: true, deleted: deletedCount };

185-207: updateClientJarTTL: solid; consider light input hardening.
Optionally reject unexpected version strings (e.g., /^[A-Za-z0-9._-]+$/) to keep TTL keys clean.

libs/ipc-handlers.js (2)

297-307: IPC handler wiring for cleanup — looks good; schedule periodically.
The channel is correct. Consider scheduling a daily cleanup in the main process (e.g., setInterval) in addition to on-demand invocations to keep disk usage in check.


314-321: IPC handler for TTL update — looks good; validate inputs.
Add a quick typeof/version-pattern check before invoking to fail fast on bad renderer calls.

preload.js (1)

51-54: Add param normalization + tiny docs on new bridge APIs.

Minor: coerce params to strings and document expected shapes to avoid accidental non-string payloads crossing IPC.

     openLocation: (locationKey) =>
         ipcRenderer.invoke('open-location', locationKey),
-    cleanUnusedClients: (latestVersion) =>
-        ipcRenderer.invoke('cleanup-unused-clients-jar', latestVersion),
-    updateClientJarTTL: (version) =>
-        ipcRenderer.invoke('update-client-jar-ttl', version),
+    /** Delete stale client jars except the latest. latestVersion: "1.2.3.4" */
+    cleanUnusedClients: (latestVersion) =>
+        ipcRenderer.invoke('cleanup-unused-clients-jar', String(latestVersion)),
+    /** Update "last launched" timestamp. version: "1.2.3.4" */
+    updateClientJarTTL: (version) =>
+        ipcRenderer.invoke('update-client-jar-ttl', String(version)),
renderer.js (1)

241-244: Normalize version before cleanup & avoid result shadowing

Trim any leading "microbot-" from clientVersion before calling cleanUnusedClients (libs/dir-module.js strips "microbot-" from jar filenames), and use a distinct response variable name for clarity.

Location: renderer.js lines 241–244.

-    const result = await window.electron.cleanUnusedClients(clientVersion);
-    if (result?.error) {
-        window.electron.logError(result.error);
-    }
+    const latestVersion = clientVersion?.replace(/^microbot-/, '');
+    const cleanupRes = await window.electron.cleanUnusedClients(latestVersion);
+    if (cleanupRes?.error) {
+        window.electron.logError(cleanupRes.error);
+    }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6426d43 and e540655.

📒 Files selected for processing (6)
  • libs/dir-module.js (1 hunks)
  • libs/ipc-handlers.js (1 hunks)
  • libs/properties.js (0 hunks)
  • package.json (1 hunks)
  • preload.js (1 hunks)
  • renderer.js (3 hunks)
💤 Files with no reviewable changes (1)
  • libs/properties.js
🧰 Additional context used
🧬 Code graph analysis (3)
preload.js (2)
renderer.js (2)
  • latestVersion (1048-1050)
  • version (22-22)
libs/dir-module.js (1)
  • version (133-133)
libs/ipc-handlers.js (2)
main.js (6)
  • require (1-1)
  • require (6-6)
  • require (8-8)
  • require (11-11)
  • require (12-16)
  • path (2-2)
libs/dir-module.js (2)
  • path (2-2)
  • version (133-133)
libs/dir-module.js (3)
main.js (6)
  • require (1-1)
  • require (6-6)
  • require (8-8)
  • require (11-11)
  • require (12-16)
  • path (2-2)
libs/ipc-handlers.js (6)
  • require (18-22)
  • require (23-27)
  • require (300-304)
  • require (315-319)
  • result (242-246)
  • result (272-281)
renderer.js (6)
  • result (24-24)
  • result (42-42)
  • result (228-228)
  • result (241-241)
  • result (556-556)
  • version (22-22)
🔇 Additional comments (2)
package.json (1)

3-3: Version bump to 3.2.3 — LGTM.
No issues spotted in this file.

libs/dir-module.js (1)

211-215: Exports — LGTM.
Matches new API surface and existing imports.

Comment thread libs/dir-module.js
Comment thread renderer.js
Comment thread renderer.js
- Avoid aborting the cleanup process on manual file deletion coming from the user.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
libs/dir-module.js (1)

160-167: Nice: ENOENT during unlink is handled without aborting cleanup.

This addresses the earlier feedback about missing-file races.

🧹 Nitpick comments (4)
libs/dir-module.js (4)

78-82: Correct JSDoc return type for getClientsJarTTL.

Document the actual { success, data?, error? } shape.

 /**
  * Check for the existence of the clients_jar_ttl.json file in the microbot directory.
  * Creating with an empty object if it does not exist.
- * @return {Object} The parsed JSON object from the file.
+ * @return {Promise<{success: boolean, data?: Record<string, number>, error?: string}>}
  */

89-97: Recover gracefully from corrupted clients_jar_ttl.json.

If the file is malformed JSON, back it up and reset instead of failing.

-            const data = await fs.readFile(filePath, 'utf8');
-            return { success: true, data: JSON.parse(data) };
+            const data = await fs.readFile(filePath, 'utf8');
+            try {
+                return { success: true, data: JSON.parse(data) };
+            } catch (parseErr) {
+                // Recover from corruption: back up and reset.
+                const backup = filePath + '.bak';
+                await fs.copyFile(filePath, backup).catch(() => {});
+                await fs.writeFile(filePath, JSON.stringify({}), 'utf8');
+                return { success: true, data: {} };
+            }

176-181: Reduce lost updates from concurrent writers by merging on-disk TTL before write.

Helps when cleanup and TTL updates run at the same time.

     const filePath = path.join(microbotDir, 'clients_jar_ttl.json');
     try {
+        // Merge with latest on-disk TTL to minimize clobbering concurrent updates.
+        try {
+            const onDiskRaw = await fs.readFile(filePath, 'utf8').catch(() => null);
+            if (onDiskRaw) {
+                const onDisk = JSON.parse(onDiskRaw);
+                ttlData = { ...onDisk, ...ttlData };
+            }
+        } catch (_) { /* ignore parse errors */ }
         await fs.writeFile(filePath, JSON.stringify(ttlData, null, 2), 'utf8');
     } catch (err) {
         return { success: false, error: err.message };
     }

146-147: Remove unused variable deletedAny.

It’s assigned but never read.

-    let deletedAny = false;
...
-                deletedAny = true;

Also applies to: 157-157

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e540655 and 3cb0f66.

📒 Files selected for processing (1)
  • libs/dir-module.js (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: Bolado
PR: chsami/Microbot-Launcher#25
File: renderer.js:42-45
Timestamp: 2025-09-11T19:35:56.332Z
Learning: In the Microbot Launcher, updating client JAR TTL should happen based on user intent to launch (before actual launch) rather than after successful launch, because failed launches due to technical issues shouldn't prevent keeping versions that users want to use.
🧬 Code graph analysis (1)
libs/dir-module.js (3)
main.js (6)
  • require (1-1)
  • require (6-6)
  • require (8-8)
  • require (11-11)
  • require (12-16)
  • path (2-2)
libs/ipc-handlers.js (6)
  • require (18-22)
  • require (23-27)
  • require (300-304)
  • require (315-319)
  • result (242-246)
  • result (272-281)
renderer.js (6)
  • result (24-24)
  • result (42-42)
  • result (228-228)
  • result (241-241)
  • result (556-556)
  • version (22-22)
🔇 Additional comments (1)
libs/dir-module.js (1)

217-220: Exports update looks good.

Public API surface aligns with new functionality.

Comment thread libs/dir-module.js
Comment thread libs/dir-module.js
- Add version format validation for client jar updates
- Check for existence of the jar file before updating
- Return specific error messages for invalid inputs and missing jars
@chsami chsami merged commit 237d0c0 into chsami:main Sep 12, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants