From 3834571ab822c51c7b7b5eb53b8a73e356815b99 Mon Sep 17 00:00:00 2001 From: Daniel Salazar Date: Fri, 20 Feb 2026 19:07:16 -0800 Subject: [PATCH] fix: don't call stat on each file in dir (#2522) * fix: decrease metering service gloabl rate of change check * fix: don't call stat on each file in dir --- .../MeteringService/MeteringService.ts | 6 +++--- src/gui/src/UI/UIItem.js | 18 ++++++------------ .../helpers/get_html_element_from_options.js | 18 ++++++------------ src/gui/src/helpers/refresh_item_container.js | 14 ++++---------- 4 files changed, 19 insertions(+), 37 deletions(-) diff --git a/src/backend/src/services/MeteringService/MeteringService.ts b/src/backend/src/services/MeteringService/MeteringService.ts index f673317c6..6f4ba9e17 100644 --- a/src/backend/src/services/MeteringService/MeteringService.ts +++ b/src/backend/src/services/MeteringService/MeteringService.ts @@ -28,7 +28,7 @@ export class MeteringService { this.#eventService = eventService; setInterval(() => { this.#checkRateOfChange(); - }, 1000 * 60 * 5); // check every 5 minutes + }, 1000 * 60 * 15); // check every 15 minutes } utilRecordUsageObject>(trackedUsageObject: T, actor: Actor, modelPrefix: string, costsOverrides?: Partial>) { @@ -688,8 +688,8 @@ export class MeteringService { return this.#kvStore.get({ key: `${METRICS_PREFIX}:lastGlobalUsageCheck` }) as Promise<{ total: number, timestamp: number } | null>; }); - if ( !lastChange || (now - lastChange.timestamp) > 4 * 60 * 1000 ) { - // only checked if more than 4 minutes from last check + if ( !lastChange || (now - lastChange.timestamp) > 14 * 60 * 1000 ) { + // only checked if more than 14 minutes from last check const globalUsage = await this.getGlobalUsage(); const currTotal = globalUsage.total; diff --git a/src/gui/src/UI/UIItem.js b/src/gui/src/UI/UIItem.js index 3184becce..7d7b27dfe 100644 --- a/src/gui/src/UI/UIItem.js +++ b/src/gui/src/UI/UIItem.js @@ -121,7 +121,7 @@ async function UIItem (options) { } const item_id = window.global_element_id++; - let last_mousedown_ts = 999999999999999; + let last_mousedown_ts = Number.MAX_SAFE_INTEGER; let rename_cancelled = false; // set options defaults @@ -139,15 +139,9 @@ async function UIItem (options) { options.immutable = (options.immutable === false || options.immutable === 0 || options.immutable === undefined ? 0 : 1); options.sort_container_after_append = (options.sort_container_after_append !== undefined ? options.sort_container_after_append : false); const is_shared_with_me = (options.path !== `/${window.user.username}` && !options.path.startsWith(`/${window.user.username}/`)); - let worker_url; - let is_worker; - if ( ! options.is_dir ) { - const stats = await puter.fs.stat({ path: options.path, returnWorkers: true }); - is_worker = stats.workers !== undefined && stats.workers.length > 0; - if ( is_worker ) { - worker_url = stats.workers[0].address; - } - } + const workers = Array.isArray(options.workers) ? options.workers : []; + const is_worker = !options.is_dir && workers.length > 0; + const worker_url = is_worker ? workers[0].address : ''; let website_url = window.determine_website_url(options.path); @@ -174,8 +168,8 @@ async function UIItem (options) { data-website_url = "${website_url ? html_encode(website_url) : ''}" data-immutable="${options.immutable}" data-is_shortcut = "${options.is_shortcut}" - data-is_worker = "${is_worker !== undefined ? 1 : 0}" - data-worker_url = "${is_worker !== undefined ? worker_url : 0}" + data-is_worker = "${is_worker ? 1 : 0}" + data-worker_url = "${is_worker ? worker_url : 0}" data-shortcut_to = "${html_encode(options.shortcut_to)}" data-shortcut_to_path = "${html_encode(options.shortcut_to_path)}" data-sortable = "${options.sortable ?? 'true'}" diff --git a/src/gui/src/helpers/get_html_element_from_options.js b/src/gui/src/helpers/get_html_element_from_options.js index 542d6d035..651e58fef 100644 --- a/src/gui/src/helpers/get_html_element_from_options.js +++ b/src/gui/src/helpers/get_html_element_from_options.js @@ -36,15 +36,9 @@ const get_html_element_from_options = async function (options) { options.immutable = (options.immutable === false || options.immutable === 0 || options.immutable === undefined ? 0 : 1); options.sort_container_after_append = (options.sort_container_after_append !== undefined ? options.sort_container_after_append : false); const is_shared_with_me = (options.path !== `/${window.user.username}` && !options.path.startsWith(`/${window.user.username}/`)); - let worker_url; - let is_worker; - if ( ! options.is_dir ) { - const stats = await puter.fs.stat({ path: options.path, returnWorkers: true }); - is_worker = stats.workers !== undefined && stats.workers.length > 0;; - if ( is_worker ) { - worker_url = stats.workers[0].address; - } - } + const workers = Array.isArray(options.workers) ? options.workers : []; + const is_worker = !options.is_dir && workers.length > 0; + const worker_url = is_worker ? workers[0].address : ''; let website_url = window.determine_website_url(options.path); @@ -71,8 +65,8 @@ const get_html_element_from_options = async function (options) { data-website_url = "${website_url ? html_encode(website_url) : ''}" data-immutable="${options.immutable}" data-is_shortcut = "${options.is_shortcut}" - data-is_worker = "${is_worker !== undefined ? 1 : 0}" - data-worker_url = "${is_worker !== undefined ? worker_url : 0}" + data-is_worker = "${is_worker ? 1 : 0}" + data-worker_url = "${is_worker ? worker_url : 0}" data-shortcut_to = "${html_encode(options.shortcut_to)}" data-shortcut_to_path = "${html_encode(options.shortcut_to_path)}" data-sortable = "${options.sortable ?? 'true'}" @@ -165,4 +159,4 @@ const get_html_element_from_options = async function (options) { return h; }; -export default get_html_element_from_options; \ No newline at end of file +export default get_html_element_from_options; diff --git a/src/gui/src/helpers/refresh_item_container.js b/src/gui/src/helpers/refresh_item_container.js index b58eecdf1..f4107e097 100644 --- a/src/gui/src/helpers/refresh_item_container.js +++ b/src/gui/src/helpers/refresh_item_container.js @@ -113,8 +113,8 @@ const refresh_item_container = function (el_item_container, options) { // remove all existing items $(el_item_container).find('.item').removeItems(); - // get items (skip subdomain fetching for faster response) - puter.fs.readdir({ path: container_path, consistency: options.consistency ?? 'eventual', no_subdomains: true }).then(async (fsentries) => { + // get items with subdomains/workers included to avoid per-item stat calls + puter.fs.readdir({ path: container_path, consistency: options.consistency ?? 'eventual' }).then(async (fsentries) => { // Check if the same folder is still loading since el_item_container's // data-path might have changed by other operations while waiting for the response to this `readdir`. if ( $(el_item_container).attr('data-path') !== container_path ) @@ -204,6 +204,7 @@ const refresh_item_container = function (el_item_container, options) { is_shortcut: fsentry.is_shortcut, shortcut_to: fsentry.shortcut_to, shortcut_to_path: fsentry.shortcut_to_path, + workers: fsentry.workers, size: fsentry.size, type: fsentry.type, modified: fsentry.modified, @@ -242,13 +243,6 @@ const refresh_item_container = function (el_item_container, options) { $(el_item_container).attr('data-sort_by'), $(el_item_container).attr('data-sort_order')); - // Fetch subdomains separately for directories and update UI - // Use the reusable function to update subdomains - // Note: This is fire-and-forget - it will update items asynchronously - window.updateSubdomainsForItems(fsentries, el_item_container).catch(err => { - console.warn('Failed to update subdomains for items:', err); - }); - if ( options.fadeInItems ) { $(el_item_container).animate({ 'opacity': '1' }, { complete: () => { @@ -299,4 +293,4 @@ const refresh_item_container = function (el_item_container, options) { }); }; -export default refresh_item_container; \ No newline at end of file +export default refresh_item_container;