diff --git a/javascript/extraNetworks.js b/javascript/extraNetworks.js index 76c737546..49e90d982 100644 --- a/javascript/extraNetworks.js +++ b/javascript/extraNetworks.js @@ -347,6 +347,8 @@ class ExtraNetworksTab { return new Promise((resolve, reject) => { let attempt = 0; const loop = () => { + console.log(`waitForServerPageReady: iter ${attempt}`); + let retry_delay_ms = 1000; setTimeout(async() => { try { await requestGetPromise( @@ -354,20 +356,29 @@ class ExtraNetworksTab { {extra_networks_tabname: this.extra_networks_tabname}, EXTRA_NETWORKS_WAIT_FOR_PAGE_READY_TIMEOUT_MS, ); + console.warn("PAGE READY:", this.extra_networks_tabname); return resolve(); } catch (error) { // If we get anything other than a timeout error, reject. // Otherwise, fall through to retry request. - if (error.status !== 408) { + if (error.status !== 408 && error.status !== 404) { return reject(`${err_prefix}: uncaught exception: ${JSON.stringify(error)}`); } + if (error.status === 404) { + retry_delay_ms = 1000; + } + if (error.status === 408) { + retry_delay_ms = 0; + } + console.log("other error:", error.status, error); } if (max_attempts !== 0 && attempt++ >= max_attempts) { return reject(`${err_prefix}: max attempts exceeded`); } else { // small delay since our request has a timeout. - setTimeout(() => loop(), 100); + console.log("retrying:", attempt); + setTimeout(loop, retry_delay_ms); } }, 0); }; @@ -376,6 +387,7 @@ class ExtraNetworksTab { } async onInitCardsData() { + console.log("onInitCardsData"); try { await this.waitForServerPageReady(); } catch (error) { @@ -396,6 +408,7 @@ class ExtraNetworksTab { } async onInitTreeData() { + console.log("onInitTreeData"); try { await this.waitForServerPageReady(); } catch (error) { @@ -416,12 +429,15 @@ class ExtraNetworksTab { } async onFetchCardsData(div_ids) { + console.log("onFetchCardsData:", div_ids); + /* try { await this.waitForServerPageReady(); } catch (error) { console.error(JSON.stringify(error)); return {}; } + */ const url = "./sd_extra_networks/fetch-cards-data"; const payload = {extra_networks_tabname: this.extra_networks_tabname, div_ids: div_ids}; @@ -439,12 +455,15 @@ class ExtraNetworksTab { } async onFetchTreeData(div_ids) { + console.log("onFetchTreeData:", div_ids); + /* try { await this.waitForServerPageReady(); } catch (error) { console.error(JSON.stringify(error)); return {}; } + */ const url = "./sd_extra_networks/fetch-tree-data"; const payload = {extra_networks_tabname: this.extra_networks_tabname, div_ids: div_ids}; @@ -977,17 +996,28 @@ function extraNetworksControlRefreshOnClick(event, tabname_full) { * event handler that refreshes the page. So what this function here does * is it manually raises a `click` event on that button. */ + event.stopPropagation(); + clearTimeout(extra_networks_refresh_internal_debounce_timer); - extra_networks_refresh_internal_debounce_timer = setTimeout(() => { + extra_networks_refresh_internal_debounce_timer = setTimeout(async () => { + const tab = extra_networks_tabs[tabname_full]; + try { + await requestGetPromise( + "./sd_extra_networks/clear-page-data", + {extra_networks_tabname: tab.extra_networks_tabname}, + 5000, + ); + console.log("cleared page data:", tab.extra_networks_tabname); + } catch (error) { + console.error("error clearing page data:", error); + } // We want to reset tab lists on refresh click so that the viewing area // shows that it is loading new data. - extra_networks_tabs[tabname_full].tree_list.clear(); - extra_networks_tabs[tabname_full].cards_list.clear(); + tab.tree_list.clear(); + tab.cards_list.clear(); // Fire an event for this button click. gradioApp().getElementById(`${tabname_full}_extra_refresh_internal`).dispatchEvent(new Event("click")); }, EXTRA_NETWORKS_REFRESH_INTERNAL_DEBOUNCE_TIMEOUT_MS); - - event.stopPropagation(); } function extraNetworksCardOnClick(event, tabname_full) { diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py index db59c2aec..dae5dc99e 100644 --- a/modules/ui_extra_networks.py +++ b/modules/ui_extra_networks.py @@ -222,6 +222,7 @@ class ExtraNetworksPage: self.extra_networks_tabname = self.name.replace(" ", "_") self.allow_prompt = True self.allow_negative_prompt = False + self.is_ready = False self.metadata = {} self.items = {} self.cards = {} @@ -238,12 +239,21 @@ class ExtraNetworksPage: self.btn_edit_metadata_tpl = shared.html("extra-networks-btn-edit-metadata.html") self.btn_dirs_view_item_tpl = shared.html("extra-networks-btn-dirs-view-item.html") - def refresh(self): - # Whenever we refresh, we want to build our datasets from scratch. + def clear_data(self) -> None: + print(f"clearing data: {self.extra_networks_tabname}") + self.is_ready = False + self.metadata = {} self.items = {} self.cards = {} self.tree = {} self.tree_roots = {} + self.nodes = {} + + def refresh(self) -> None: + print(f"refreshing: {self.extra_networks_tabname}") + # Whenever we refresh, we want to build our datasets from scratch. + self.is_ready = False + self.clear_data() def read_user_metadata(self, item, use_cache=True): filename = os.path.normpath(item.get("filename", None)) @@ -1003,6 +1013,19 @@ def init_cards_data(tabname: str = "", extra_networks_tabname: str = "") -> JSON return JSONResponse(data) +def clear_page_data(extra_networks_tabname: str = "") -> JSONResponse: + """Returns whether the specified page is ready for fetching data. + + Status Codes: + 200 on success + 404 if tabname doesnt exist or other errors. + """ + page = get_page_by_name(extra_networks_tabname) + + page.clear_data() + + return JSONResponse({}, status_code=200) + def page_is_ready(extra_networks_tabname: str = "") -> JSONResponse: """Returns whether the specified page is ready for fetching data. @@ -1012,6 +1035,7 @@ def page_is_ready(extra_networks_tabname: str = "") -> JSONResponse: """ page = get_page_by_name(extra_networks_tabname) + print(f"page_is_ready: {extra_networks_tabname} => {page.is_ready}, {len(page.items)}, {len(list(page.list_items()))}") if len(page.items) == len(list(page.list_items())): return JSONResponse({}, status_code=200) else: @@ -1071,6 +1095,7 @@ def add_pages_to_demo(app): app.add_api_route("/sd_extra_networks/fetch-tree-data", fetch_tree_data, methods=["GET"]) app.add_api_route("/sd_extra_networks/fetch-cards-data", fetch_cards_data, methods=["GET"]) app.add_api_route("/sd_extra_networks/page-is-ready", page_is_ready, methods=["GET"]) + app.add_api_route("/sd_extra_networks/clear-page-data", clear_page_data, methods=["GET"]) def quote_js(s): @@ -1166,8 +1191,10 @@ def create_ui(interface: gr.Blocks, unrelated_tabs, tabname): def refresh(tabname_full): page = ui.stored_extra_pages[tabname_full] + page.is_ready = False page.refresh() ui.pages_contents[tabname_full] = page.create_html(ui.tabname) + page.is_ready = True return list(ui.pages_contents.values()) button_refresh = gr.Button(