diff --git a/backend/btrixcloud/crawls.py b/backend/btrixcloud/crawls.py index 74897c63ab..e45ae1ac27 100644 --- a/backend/btrixcloud/crawls.py +++ b/backend/btrixcloud/crawls.py @@ -441,6 +441,13 @@ async def inc_crawl_exec_time(self, crawl_id, exec_time, last_updated_time): }, ) + async def get_crawl_exec_last_update_time(self, crawl_id): + """get crawl last updated time""" + res = await self.crawls.find_one( + {"_id": crawl_id, "type": "crawl"}, projection=["_lut"] + ) + return res and res.get("_lut") + async def get_crawl_state(self, crawl_id): """return current crawl state of a crawl""" res = await self.crawls.find_one( diff --git a/backend/btrixcloud/operator/crawls.py b/backend/btrixcloud/operator/crawls.py index bab54232bb..e050b09ce4 100644 --- a/backend/btrixcloud/operator/crawls.py +++ b/backend/btrixcloud/operator/crawls.py @@ -232,7 +232,9 @@ async def sync_crawls(self, data: MCSyncData): else: status.scale = crawl.scale - status.lastUpdatedTime = to_k8s_date(dt_now()) + now = dt_now() + await self.crawl_ops.inc_crawl_exec_time(crawl_id, 0, now) + status.lastUpdatedTime = to_k8s_date(now) children = self._load_redis(params, status, data.children) @@ -828,12 +830,15 @@ async def increment_pod_exec_time( """inc exec time tracking""" now = dt_now() - if not status.lastUpdatedTime: + update_start_time = await self.crawl_ops.get_crawl_exec_last_update_time( + crawl_id + ) + + if not update_start_time: + await self.crawl_ops.inc_crawl_exec_time(crawl_id, 0, now) status.lastUpdatedTime = to_k8s_date(now) return - update_start_time = from_k8s_date(status.lastUpdatedTime) - reason = None update_duration = (now - update_start_time).total_seconds() @@ -907,16 +912,6 @@ async def increment_pod_exec_time( max_duration = max(duration, max_duration) if exec_time: - if not await self.crawl_ops.inc_crawl_exec_time( - crawl_id, exec_time, status.lastUpdatedTime - ): - # if lastUpdatedTime is same as previous, something is wrong, don't update! - print( - "Already updated for lastUpdatedTime, skipping execTime update!", - flush=True, - ) - return - await self.org_ops.inc_org_time_stats(oid, exec_time, True) status.crawlExecTime += exec_time status.elapsedCrawlTime += max_duration @@ -926,6 +921,7 @@ async def increment_pod_exec_time( flush=True, ) + await self.crawl_ops.inc_crawl_exec_time(crawl_id, exec_time, now) status.lastUpdatedTime = to_k8s_date(now) def should_mark_waiting(self, state, started): diff --git a/frontend/src/components/ui/copy-button.ts b/frontend/src/components/ui/copy-button.ts index 2d9b27ffe4..5280ca22d0 100644 --- a/frontend/src/components/ui/copy-button.ts +++ b/frontend/src/components/ui/copy-button.ts @@ -57,6 +57,8 @@ export class CopyButton extends LitElement { ? this.content : msg("Copy")} ?hoist=${this.hoist} + @sl-hide=${this.stopProp} + @sl-after-hide=${this.stopProp} > -
+
${msg("Pending Exclusions")} ${this.renderBadge()}
${this.total && this.total > this.pageSize ? html` { + // if escaped version of string, with '\' removed matches string, then consider it + // to be matching text, otherwise, regex + const isText = regexEscape(str.replace(/\\/g, "")) === str; return { - // if escaped version of string, with '\' removed matches string, then consider it - // to be matching text, otherwise, regex - type: regexEscape(str.replace(/\\/g, "")) === str ? "text" : "regex", - value: str, + type: isText ? "text" : "regex", + value: isText ? regexUnescape(str) : str, }; }); } diff --git a/frontend/src/pages/org/workflow-editor.ts b/frontend/src/pages/org/workflow-editor.ts index b5a483bf5b..87b73fef30 100644 --- a/frontend/src/pages/org/workflow-editor.ts +++ b/frontend/src/pages/org/workflow-editor.ts @@ -27,7 +27,7 @@ import uniq from "lodash/fp/uniq"; import Fuse from "fuse.js"; import LiteElement, { html } from "@/utils/LiteElement"; -import { regexEscape } from "@/utils/string"; +import { regexEscape, regexUnescape } from "@/utils/string"; import type { AuthState } from "@/utils/AuthService"; import { getUTCSchedule, @@ -495,7 +495,7 @@ export class CrawlConfigEditor extends LiteElement { if (primarySeedConfig.include?.length) { formState.customIncludeUrlList = primarySeedConfig.include // Unescape regex - .map((url) => url.replace(/(\\|\/\.\*)/g, "")) + .map(regexUnescape) .join("\n"); // if we have additional include URLs, set to "custom" scope here // to indicate 'Custom Page Prefix' option diff --git a/frontend/src/utils/string.ts b/frontend/src/utils/string.ts index ef262d41e8..d84d1cf4b6 100644 --- a/frontend/src/utils/string.ts +++ b/frontend/src/utils/string.ts @@ -5,3 +5,7 @@ export function regexEscape(s: unknown) { return String(s).replace(/[\\^$*+?.()|[\]{}]/g, "\\$&"); } + +export function regexUnescape(s: unknown) { + return String(s).replace(/(\\|\/\.\*)/g, ""); +}