Skip to content
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

[WEB-2001] fix: Issue local cache fixes #5703

Merged
merged 8 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion web/core/components/issues/title-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export const IssueTitleInput: FC<IssueTitleInputProps> = observer((props) => {
[setIsSubmitting]
);

if (disabled) return <div className="text-2xl font-medium">{title}</div>;
if (disabled) return <div className="text-2xl font-medium whitespace-pre-line">{title}</div>;

return (
<div className="flex flex-col gap-1.5">
Expand Down
28 changes: 13 additions & 15 deletions web/core/local-db/storage.sqlite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,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 { getGroupedIssueResults, getSubGroupedIssueResults } from "./utils/utils";
import { logError, getGroupedIssueResults, getSubGroupedIssueResults, logInfo, log } from "./utils/utils";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Action Required: Direct console calls detected.

The verification script found multiple direct console.log, console.error, and console.warn calls that should be replaced with the new logging functions to maintain consistent log management.

Examples of affected files:

  • web/app/workspace-invitations/page.tsx
  • web/core/components/issues/issue-detail/root.tsx
  • web/helpers/string.helper.ts
  • packages/editor/src/core/plugins/image/restore-image.ts
  • admin/app/authentication/github/form.tsx
  • (and many others as listed in the script output)

Please refactor these instances to use the appropriate logging functions (logError, logInfo, log) from ./utils/utils to ensure consistency and improve log management across the codebase.

🔗 Analysis chain

LGTM: Improved logging imports.

The introduction of specific logging functions (logError, logInfo, log) is a good practice for better log management and filtering.

To ensure consistency across the codebase, please run the following script to check for any remaining direct console calls that should be replaced:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for direct console calls that should be replaced with new logging functions.

# Test: Search for direct console calls. Expect: No results or only intentional direct console calls.
rg --type typescript 'console\.(log|error|info|warn)'

Length of output: 77


Script:

#!/bin/bash
# Description: Check for direct console calls that should be replaced with new logging functions.

# Test: Search for direct console calls in TypeScript files. Expect: No results or only intentional direct console calls.
rg --type ts 'console\.(log|error|info|warn)'

Length of output: 21289


declare module "@sqlite.org/sqlite-wasm" {
export function sqlite3Worker1Promiser(...args: any): any;
Expand All @@ -24,9 +24,6 @@ declare module "@sqlite.org/sqlite-wasm" {
const DB_VERSION = 1;
const PAGE_SIZE = 1000;
const BATCH_SIZE = 200;
const log = console.log;
const error = console.error;
const info = console.info;

type TProjectStatus = {
issues: { status: undefined | "loading" | "ready" | "error" | "syncing"; sync: Promise<void> | undefined };
Expand Down Expand Up @@ -72,7 +69,7 @@ export class Storage {
await this._initialize(workspaceSlug);
return true;
} catch (err) {
error(err);
logError(err);
this.status = "error";
return false;
}
Expand All @@ -92,7 +89,7 @@ export class Storage {
return false;
}

info("Loading and initializing SQLite3 module...");
logInfo("Loading and initializing SQLite3 module...");

this.workspaceSlug = workspaceSlug;
this.dbName = workspaceSlug;
Expand Down Expand Up @@ -141,7 +138,7 @@ export class Storage {

await this.setOption("DB_VERSION", DB_VERSION.toString());
} catch (err) {
error(err);
logError(err);
throw err;
}

Expand Down Expand Up @@ -179,15 +176,16 @@ export class Storage {
this.setSync(projectId, sync);
await sync;
} catch (e) {
logError(e);
this.setStatus(projectId, "error");
}
};

_syncIssues = async (projectId: string) => {
console.log("### Sync started");
log("### Sync started");
let status = this.getStatus(projectId);
if (status === "loading" || status === "syncing") {
info(`Project ${projectId} is already loading or syncing`);
logInfo(`Project ${projectId} is already loading or syncing`);
return;
}
const syncPromise = this.getSync(projectId);
Expand Down Expand Up @@ -235,7 +233,7 @@ export class Storage {
if (syncedAt) {
await syncDeletesToLocal(this.workspaceSlug, projectId, { updated_at__gt: syncedAt });
}
console.log("### Time taken to add issues", performance.now() - start);
log("### Time taken to add issues", performance.now() - start);

if (status === "loading") {
await createIndexes();
Expand All @@ -252,7 +250,7 @@ export class Storage {

getLastUpdatedIssue = async (projectId: string) => {
const lastUpdatedIssue = await runQuery(
`select id, name, updated_at , sequence_id from issues where project_id='${projectId}' order by datetime(updated_at) desc limit 1`
`select id, name, updated_at , sequence_id from issues WHERE project_id='${projectId}' AND is_local_update IS NULL order by datetime(updated_at) desc limit 1 `
);

if (lastUpdatedIssue.length) {
Expand All @@ -270,7 +268,7 @@ export class Storage {
};

getIssues = async (workspaceSlug: string, projectId: string, queries: any, config: any) => {
console.log("#### Queries", queries);
log("#### Queries", queries);

const currentProjectStatus = this.getStatus(projectId);
if (
Expand All @@ -280,7 +278,7 @@ export class Storage {
currentProjectStatus === "error" ||
!rootStore.user.localDBEnabled
) {
info(`Project ${projectId} is loading, falling back to server`);
logInfo(`Project ${projectId} is loading, falling back to server`);
const issueService = new IssueService();
return await issueService.getIssuesFromServer(workspaceSlug, projectId, queries);
}
Expand All @@ -307,7 +305,7 @@ export class Storage {
const parsingStart = performance.now();
let issueResults = issuesRaw.map((issue: any) => formatLocalIssue(issue));

console.log("#### Issue Results", issueResults.length);
log("#### Issue Results", issueResults.length);

const parsingEnd = performance.now();

Expand All @@ -326,7 +324,7 @@ export class Storage {
Parsing: parsingEnd - parsingStart,
Grouping: groupingEnd - grouping,
};
console.log(issueResults);
log(issueResults);
console.table(times);

const total_pages = Math.ceil(total_count / Number(pageSize));
Expand Down
8 changes: 4 additions & 4 deletions web/core/local-db/utils/load-issues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ export const deleteIssueFromLocal = async (issue_id: any) => {
persistence.db.exec(deleteMetaQuery);
persistence.db.exec("COMMIT;");
};

export const updateIssue = async (issue: TIssue) => {
// @todo: Update deletes the issue description from local. Implement a separate update.
export const updateIssue = async (issue: TIssue & { is_local_update: number }) => {
if (document.hidden || !rootStore.user.localDBEnabled) return;

const issue_id = issue.id;
Expand Down Expand Up @@ -82,10 +82,10 @@ const stageIssueInserts = (issue: any) => {
return "";
}
if (typeof value === "object") {
return `'${JSON.stringify(value)}'`;
return `'${JSON.stringify(value).replace(/'/g, "''")}'`;
}
if (typeof value === "string") {
return `'${value}'`;
return `'${value.replace(/'/g, "''")}'`;
}
return value;
})
Expand Down
9 changes: 5 additions & 4 deletions web/core/local-db/utils/query-constructor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
singleFilterConstructor,
translateQueryParams,
} from "./query.utils";
import { log } from "./utils";
export const SPECIAL_ORDER_BY = {
labels__name: "labels",
"-labels__name": "labels",
Expand Down Expand Up @@ -47,7 +48,7 @@ export const issueFilterQueryConstructor = (workspaceSlug: string, projectId: st

`;

console.log("###", sql);
log("###", sql);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Issues Found: Inconsistent Logging Practices Across the Codebase

The shell script analysis revealed multiple instances of console.log remaining in various TypeScript files within the web/ directory. To ensure consistent and secure logging, it's recommended to replace all console.log statements with the custom log function. This will help in managing logs effectively and prevent potential exposure of sensitive information.

Affected Files:

  • web/helpers/string.helper.ts
  • web/core/store/project/project.store.ts
  • web/core/services/file.service.ts
  • web/core/store/cycle.store.ts
  • web/core/local-db/storage.sqlite.ts
  • web/core/local-db/utils/utils.ts
  • web/core/local-db/utils/indexes.ts
  • web/core/hooks/use-multiple-select.ts
  • web/core/components/workspace/sidebar/favorites/favorites-menu.tsx
  • web/core/components/workspace/settings/member-columns.tsx
  • web/core/components/project/settings/member-columns.tsx
  • web/core/components/project/member-list-item.tsx
  • web/core/components/project-states/create-update/form.tsx
  • web/app/installations/[provider]/page.tsx
🔗 Analysis chain

LGTM: Replaced console.log with custom log function.

The change is consistent with the described modifications. However, consider the following:

  1. Ensure that the custom log function handles sensitive information appropriately.
  2. Review if logging SQL queries is necessary in production environments.
  3. Consider using log levels (e.g., debug, info, warn) instead of prefixes like "###" for better log management.

To verify logging practices, run:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for other instances of console.log and log function usage
rg --type typescript 'console\.log|log\(' web/

Length of output: 83


Script:

#!/bin/bash
# Check for other instances of console.log and log function usage in TypeScript files
rg 'console\.log|log\(' web/ --type-add 'typescript:*.{ts,tsx}' --type typescript

Length of output: 3722


return sql;
}
Expand All @@ -63,7 +64,7 @@ export const issueFilterQueryConstructor = (workspaceSlug: string, projectId: st
WHERE rank <= ${per_page}
`;

console.log("###", sql);
log("###", sql);

return sql;
}
Expand Down Expand Up @@ -119,7 +120,7 @@ export const issueFilterQueryConstructor = (workspaceSlug: string, projectId: st
`;
sql += ` group by i.id ${orderByString} LIMIT ${pageSize} OFFSET ${offset * 1 + page * pageSize};`;

console.log("######$$$", sql);
log("######$$$", sql);
return sql;
}

Expand Down Expand Up @@ -148,7 +149,7 @@ export const issueFilterQueryConstructor = (workspaceSlug: string, projectId: st
// Add offset and paging to query
sql += ` LIMIT ${pageSize} OFFSET ${offset * 1 + page * pageSize};`;

console.log("$$$", sql);
log("$$$", sql);
return sql;
};

Expand Down
1 change: 1 addition & 0 deletions web/core/local-db/utils/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const issueSchema: Schema = {
assignee_ids: "TEXT",
module_ids: "TEXT",
description_html: "TEXT",
is_local_update: "INTEGER",
};

export const issueMetaSchema: Schema = {
Expand Down
3 changes: 2 additions & 1 deletion web/core/local-db/utils/tables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ import {
memberSchema,
optionsSchema,
} from "./schemas";
import { log } from "./utils";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Remaining console.log statements found.

While the centralized log function is implemented, several console.log calls still exist across the codebase:

  • Local-DB Directory:

    • ./web/core/local-db/utils/utils.ts
    • ./web/core/local-db/utils/indexes.ts
  • Stores and Services:

    • ./web/core/store/project/project.store.ts
    • ./web/core/services/file.service.ts
  • Helpers and Components:

    • ./web/helpers/string.helper.ts
    • ./web/core/components/...

Please replace these console.log statements with the centralized log function to ensure consistent logging practices.

🔗 Analysis chain

Approve the addition of centralized logging utility.

The introduction of a centralized log function from ./utils is a good practice for maintaining consistent logging across the application.

To ensure this change is implemented consistently, let's verify the log function's implementation and its usage across the codebase:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the implementation and usage of the `log` function

# Test 1: Check the implementation of the `log` function
echo "Checking the implementation of the log function:"
rg --type typescript 'export (const|function) log' ./web/core/local-db/utils/

# Test 2: Check for any remaining direct console.log calls in the local-db directory
echo "Checking for any remaining direct console.log calls in the local-db directory:"
rg --type typescript 'console\.log' ./web/core/local-db/

# Test 3: Check the usage of the new log function across the codebase
echo "Checking the usage of the new log function across the codebase:"
rg --type typescript 'log\(' ./web/

Length of output: 692


Script:

#!/bin/bash
# Description: Verify the implementation and usage of the `log` function without using --type flag

# Test 1: Check the implementation of the `log` function
echo "Checking the implementation of the log function:"
rg 'export (const|function) log' ./web/core/local-db/utils/ --glob '*.ts' --glob '*.tsx'

# Test 2: Check for any remaining direct console.log calls in the local-db directory
echo "Checking for any remaining direct console.log calls in the local-db directory:"
rg 'console\.log' ./web/core/local-db/ --glob '*.ts' --glob '*.tsx'

# Test 3: Check the usage of the new log function across the codebase
echo "Checking the usage of the new log function across the codebase:"
rg 'log\(' ./web/ --glob '*.ts' --glob '*.tsx'

Length of output: 4700


const createTableSQLfromSchema = (tableName: string, schema: Schema) => {
let sql = `CREATE TABLE IF NOT EXISTS ${tableName} (`;
sql += Object.keys(schema)
.map((key) => `'${key}' ${schema[key]}`)
.join(", ");
sql += `);`;
console.log("#####", sql);
log("#####", sql);
return sql;
};

Expand Down
12 changes: 8 additions & 4 deletions web/core/local-db/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ import { TIssue } from "@plane/types";
import { rootStore } from "@/lib/store-context";
import { updateIssue } from "./load-issues";

export const log = console.log;

// export const log = () => {};
export const log = (...args: any) => {
if ((window as any).DEBUG) {
console.log(...args);
}
};
export const logError = console.error;
export const logInfo = console.info;
Comment on lines +11 to +12
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider applying conditional logging to logError and logInfo

The addition of logError and logInfo functions provides a consistent interface for different types of logging. However, unlike the log function, these new functions do not implement conditional logging based on the DEBUG flag.

For consistency and to have better control over all types of logging, consider applying the same conditional logic to these functions:

export const logError = (...args: any[]) => {
  if (window.DEBUG) {
    console.error(...args);
  }
};

export const logInfo = (...args: any[]) => {
  if (window.DEBUG) {
    console.info(...args);
  }
};

This change would ensure that all logging functions behave consistently and can be controlled via the DEBUG flag, which is particularly useful when transitioning between development and production environments.


export const updatePersistentLayer = async (issueIds: string | string[]) => {
if (typeof issueIds === "string") {
Expand Down Expand Up @@ -44,7 +48,7 @@ export const updatePersistentLayer = async (issueIds: string | string[]) => {
"module_ids",
"type_id",
]);
updateIssue(issuePartial);
updateIssue({ ...issuePartial, is_local_update: 1 });
}
});
};
Expand Down
13 changes: 1 addition & 12 deletions web/core/services/issue/issue.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { persistence } from "@/local-db/storage.sqlite";
// services

import { addIssue, addIssuesBulk, deleteIssueFromLocal } from "@/local-db/utils/load-issues";
import { updatePersistentLayer } from "@/local-db/utils/utils";
import { APIService } from "@/services/api.service";

export class IssueService extends APIService {
Expand All @@ -24,10 +23,7 @@ export class IssueService extends APIService {

async createIssue(workspaceSlug: string, projectId: string, data: Partial<TIssue>): Promise<TIssue> {
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/`, data)
.then((response) => {
updatePersistentLayer(response?.data?.id);
return response?.data;
})
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
Expand Down Expand Up @@ -147,7 +143,6 @@ export class IssueService extends APIService {
issues: string[];
}
) {
updatePersistentLayer(data.issues);
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/cycle-issues/`, data)
.then((response) => response?.data)
.catch((error) => {
Expand Down Expand Up @@ -177,7 +172,6 @@ export class IssueService extends APIService {
relation?: "blocking" | null;
}
) {
updatePersistentLayer(issueId);
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/issue-relation/`, data)
.then((response) => response?.data)
.catch((error) => {
Expand Down Expand Up @@ -218,7 +212,6 @@ export class IssueService extends APIService {
}

async patchIssue(workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>): Promise<any> {
updatePersistentLayer(issueId);
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/`, data)
.then((response) => response?.data)
.catch((error) => {
Expand Down Expand Up @@ -249,7 +242,6 @@ export class IssueService extends APIService {
issueId: string,
data: { sub_issue_ids: string[] }
): Promise<TIssueSubIssues> {
updatePersistentLayer([issueId, ...data.sub_issue_ids]);
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/sub-issues/`, data)
.then((response) => response?.data)
.catch((error) => {
Expand All @@ -271,7 +263,6 @@ export class IssueService extends APIService {
issueId: string,
data: Partial<TIssueLink>
): Promise<TIssueLink> {
updatePersistentLayer(issueId);
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/issue-links/`, data)
.then((response) => response?.data)
.catch((error) => {
Expand All @@ -286,7 +277,6 @@ export class IssueService extends APIService {
linkId: string,
data: Partial<TIssueLink>
): Promise<TIssueLink> {
updatePersistentLayer(issueId);
return this.patch(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/issue-links/${linkId}/`,
data
Expand All @@ -298,7 +288,6 @@ export class IssueService extends APIService {
}

async deleteIssueLink(workspaceSlug: string, projectId: string, issueId: string, linkId: string): Promise<any> {
updatePersistentLayer(issueId);
return this.delete(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/issue-links/${linkId}/`
)
Expand Down
3 changes: 3 additions & 0 deletions web/core/store/issue/helpers/base-issues.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
} from "@plane/types";
import { EIssueLayoutTypes, ISSUE_PRIORITIES } from "@/constants/issue";
import { convertToISODateString } from "@/helpers/date-time.helper";
import { updatePersistentLayer } from "@/local-db/utils/utils";
import { CycleService } from "@/services/cycle.service";
import { IssueArchiveService, IssueDraftService, IssueService } from "@/services/issue";
import { ModuleService } from "@/services/module.service";
Expand Down Expand Up @@ -529,6 +530,8 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore {
// If shouldUpdateList is true, call fetchParentStats
shouldUpdateList && (await this.fetchParentStats(workspaceSlug, projectId));

updatePersistentLayer(response.id);

return response;
}

Expand Down
6 changes: 6 additions & 0 deletions web/core/store/issue/issue-details/sub_issues.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
TSubIssuesStateDistribution,
} from "@plane/types";
// services
import { updatePersistentLayer } from "@/local-db/utils/utils";
import { IssueService } from "@/services/issue";
// store
import { IIssueDetail } from "./root.store";
Expand Down Expand Up @@ -180,6 +181,7 @@ export class IssueSubIssuesStore implements IIssueSubIssuesStore {
[parentIssueId, "sub_issues_count"],
this.subIssues[parentIssueId].length
);
updatePersistentLayer([parentIssueId, ...issueIds]);

return;
};
Expand Down Expand Up @@ -277,6 +279,8 @@ export class IssueSubIssuesStore implements IIssueSubIssuesStore {
);
});

updatePersistentLayer([parentIssueId]);

return;
};

Expand Down Expand Up @@ -310,6 +314,8 @@ export class IssueSubIssuesStore implements IIssueSubIssuesStore {
);
});

updatePersistentLayer([parentIssueId]);

return;
};

Expand Down
Loading
Loading