[WEB-2001] feat: Fix local cache issues r4 (#5726)
* - Handle single quotes in load workspace queries - Add IS null where condition in query utils * Fix description_html being lost * Change secondary order to sequence_id * Fix update persistence layer * Add instrumentation * - Fallback to server incase of any error
This commit is contained in:
parent
927d265209
commit
33f6c1fe9e
4 changed files with 59 additions and 9 deletions
|
|
@ -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();
|
||||
|
||||
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);
|
||||
}
|
||||
// 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");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ const getSingleFilterFields = (queries: any) => {
|
|||
export const getIssueFieldsFragment = () => {
|
||||
const { description_html, ...filtered } = issueSchema;
|
||||
const keys = Object.keys(filtered);
|
||||
const sql = ` ${keys.map((key, index) => `i.${key}`).join(`,
|
||||
const sql = ` ${keys.map((key) => `i.${key}`).join(`,
|
||||
`)}`;
|
||||
return sql;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import * as Sentry from "@sentry/nextjs";
|
||||
// types
|
||||
import type {
|
||||
IIssueDisplayProperties,
|
||||
|
|
@ -69,7 +70,10 @@ export class IssueService extends APIService {
|
|||
}
|
||||
|
||||
async getIssues(workspaceSlug: string, projectId: string, queries?: any, config = {}): Promise<TIssuesResponse> {
|
||||
const response = await persistence.getIssues(workspaceSlug, projectId, queries, config);
|
||||
const response = await Sentry.startSpan({ name: "GET_ISSUES" }, async () => {
|
||||
const res = await persistence.getIssues(workspaceSlug, projectId, queries, config);
|
||||
return res;
|
||||
});
|
||||
return response as TIssuesResponse;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue