-
Notifications
You must be signed in to change notification settings - Fork 3.6k
[WEB-2001] feat: Fix local cache issues r4 #5726
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
be8f069
215889c
00c48c3
5cece0f
53e9d64
8ae412e
e16421e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| import * as Sentry from "@sentry/nextjs"; | ||
| import set from "lodash/set"; | ||
| // plane | ||
| import { EIssueGroupBYServerToProperty } from "@plane/constants"; | ||
|
|
@@ -15,7 +16,7 @@ import { loadWorkSpaceData } from "./utils/load-workspace"; | |
| import { issueFilterCountQueryConstructor, issueFilterQueryConstructor } from "./utils/query-constructor"; | ||
| import { runQuery } from "./utils/query-executor"; | ||
| import { createTables } from "./utils/tables"; | ||
| import { logError, getGroupedIssueResults, getSubGroupedIssueResults, logInfo, log } from "./utils/utils"; | ||
| import { getGroupedIssueResults, getSubGroupedIssueResults, log, logError, logInfo } from "./utils/utils"; | ||
|
|
||
| declare module "@sqlite.org/sqlite-wasm" { | ||
| export function sqlite3Worker1Promiser(...args: any): any; | ||
|
|
@@ -67,7 +68,7 @@ export class Storage { | |
| this.reset(); | ||
| } | ||
| try { | ||
| await this._initialize(workspaceSlug); | ||
| await Sentry.startSpan({ name: "INIT_DB" }, async () => await this._initialize(workspaceSlug)); | ||
| return true; | ||
| } catch (err) { | ||
| logError(err); | ||
|
|
@@ -148,7 +149,9 @@ export class Storage { | |
|
|
||
| syncWorkspace = async () => { | ||
| if (document.hidden || !rootStore.user.localDBEnabled) return; // return if the window gets hidden | ||
| loadWorkSpaceData(this.workspaceSlug); | ||
| await Sentry.startSpan({ name: "LOAD_WS", attributes: { slug: this.workspaceSlug } }, async () => { | ||
| await loadWorkSpaceData(this.workspaceSlug); | ||
| }); | ||
| }; | ||
|
|
||
| syncProject = async (projectId: string) => { | ||
|
|
@@ -173,7 +176,7 @@ export class Storage { | |
| if (document.hidden || !rootStore.user.localDBEnabled) return false; // return if the window gets hidden | ||
|
|
||
| try { | ||
| const sync = this._syncIssues(projectId); | ||
| const sync = Sentry.startSpan({ name: `SYNC_ISSUES` }, () => this._syncIssues(projectId)); | ||
| this.setSync(projectId, sync); | ||
| await sync; | ||
| } catch (e) { | ||
|
|
@@ -183,6 +186,8 @@ export class Storage { | |
| }; | ||
|
|
||
| _syncIssues = async (projectId: string) => { | ||
| const activeSpan = Sentry.getActiveSpan(); | ||
|
|
||
|
Comment on lines
+189
to
+190
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Potential issues with active span management In several places, you retrieve the active span and set attributes:
Concerns:
Recommendations:
Also applies to: 251-254, 366-376 |
||
| log("### Sync started"); | ||
| let status = this.getStatus(projectId); | ||
| if (status === "loading" || status === "syncing") { | ||
|
|
@@ -242,6 +247,11 @@ export class Storage { | |
| this.setOption(projectId, "ready"); | ||
| this.setStatus(projectId, "ready"); | ||
| this.setSync(projectId, undefined); | ||
|
|
||
| activeSpan?.setAttributes({ | ||
| projectId: projectId, | ||
| count: response.total_count, | ||
| }); | ||
| }; | ||
|
|
||
| getIssueCount = async (projectId: string) => { | ||
|
|
@@ -279,7 +289,9 @@ export class Storage { | |
| currentProjectStatus === "error" || | ||
| !rootStore.user.localDBEnabled | ||
| ) { | ||
| logInfo(`Project ${projectId} is loading, falling back to server`); | ||
| if (rootStore.user.localDBEnabled) { | ||
| logInfo(`Project ${projectId} is loading, falling back to server`); | ||
| } | ||
| const issueService = new IssueService(); | ||
| return await issueService.getIssuesFromServer(workspaceSlug, projectId, queries); | ||
| } | ||
|
|
@@ -289,7 +301,15 @@ export class Storage { | |
| const query = issueFilterQueryConstructor(this.workspaceSlug, projectId, queries); | ||
| const countQuery = issueFilterCountQueryConstructor(this.workspaceSlug, projectId, queries); | ||
| const start = performance.now(); | ||
| const [issuesRaw, count] = await Promise.all([runQuery(query), runQuery(countQuery)]); | ||
| let issuesRaw: any[] = []; | ||
| let count: any[]; | ||
| try { | ||
| [issuesRaw, count] = await Promise.all([runQuery(query), runQuery(countQuery)]); | ||
| } catch (e) { | ||
| logError(e); | ||
| const issueService = new IssueService(); | ||
| return await issueService.getIssuesFromServer(workspaceSlug, projectId, queries); | ||
| } | ||
|
Comment on lines
+304
to
+312
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Enhance user feedback when falling back to server due to query failure In the try {
[issuesRaw, count] = await Promise.all([runQuery(query), runQuery(countQuery)]);
} catch (e) {
logError(e);
const issueService = new IssueService();
return await issueService.getIssuesFromServer(workspaceSlug, projectId, queries);
}Recommendation:
Example: logError(e);
+ logInfo('Local query failed, fetching issues from server');
const issueService = new IssueService();
return await issueService.getIssuesFromServer(workspaceSlug, projectId, queries); |
||
| // const issuesRaw = await runQuery(query); | ||
| const end = performance.now(); | ||
|
|
||
|
|
@@ -318,6 +338,8 @@ export class Storage { | |
| issueResults = getGroupedIssueResults(issueResults); | ||
| } | ||
| } | ||
| const groupCount = group_by ? Object.keys(issueResults).length : undefined; | ||
| const subGroupCount = sub_group_by ? Object.keys(issueResults[Object.keys(issueResults)[0]]).length : undefined; | ||
| const groupingEnd = performance.now(); | ||
|
|
||
| const times = { | ||
|
|
@@ -341,6 +363,17 @@ export class Storage { | |
| total_pages, | ||
| }; | ||
|
|
||
| const activeSpan = Sentry.getActiveSpan(); | ||
| activeSpan?.setAttributes({ | ||
| projectId, | ||
| count: total_count, | ||
| groupBy: group_by, | ||
| subGroupBy: sub_group_by, | ||
| queries: queries, | ||
| local: true, | ||
| groupCount, | ||
| subGroupCount, | ||
| }); | ||
| return out; | ||
| }; | ||
|
|
||
|
|
@@ -353,6 +386,7 @@ export class Storage { | |
| return formatLocalIssue(issues[0]); | ||
| } | ||
| } catch (err) { | ||
| logError(err); | ||
| console.warn("unable to fetch issue from local db"); | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| import * as Sentry from "@sentry/nextjs"; | ||
| import pick from "lodash/pick"; | ||
| import { TIssue } from "@plane/types"; | ||
| import { rootStore } from "@/lib/store-context"; | ||
|
|
@@ -9,7 +10,13 @@ export const log = (...args: any) => { | |
| console.log(...args); | ||
| } | ||
| }; | ||
| export const logError = console.error; | ||
| export const logError = (e: any) => { | ||
| if (e?.result?.errorClass === "SQLite3Error") { | ||
| e = parseSQLite3Error(e); | ||
| } | ||
| Sentry.captureException(e); | ||
| console.log(e); | ||
| }; | ||
| export const logInfo = console.info; | ||
|
|
||
| export const updatePersistentLayer = async (issueIds: string | string[]) => { | ||
|
|
@@ -140,3 +147,8 @@ export const getSubGroupedIssueResults = ( | |
| }; | ||
|
|
||
| export const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); | ||
|
|
||
| const parseSQLite3Error = (error: any) => { | ||
| error.result = JSON.stringify(error.result); | ||
| return error; | ||
| }; | ||
|
Comment on lines
+151
to
+154
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Improve error parsing and handling in While the
Consider refactoring the function as follows: const parseSQLite3Error = (error: any): any => {
try {
const parsedError = {
...error,
result: typeof error.result === 'object' ? JSON.stringify(error.result) : error.result
};
return parsedError;
} catch (jsonError) {
console.warn('Failed to stringify SQLite3Error result:', jsonError);
return {
...error,
result: 'Failed to stringify error result'
};
}
};This version:
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent usage of
Sentry.startSpanThe
Sentry.startSpanmethod is used inconsistently across the codebase:Line 71:
Used with
awaitand anasynccallback.Lines 152-154:
Similar usage with
awaitand anasynccallback.Line 179:
Here,
Sentry.startSpanis called withoutawait, and the result is assigned toconst sync.Recommendations:
Sentry.startSpan. Decide whether toawaitthe function call and whether to use anasynccallback consistently.Sentry.startSpanis the correct method to use. According to the Sentry SDK documentation, you might need to useSentry.startTransactionor create a span from an existing transaction.Sentry.startSpanaccepts a callback function. If not, you may need to manually start and finish the span.Also applies to: 152-154, 179-179