Skip to content

Commit

Permalink
Merge pull request #2057 from cardstack/invalidation-improvement
Browse files Browse the repository at this point in the history
Invalidation performance improvement
  • Loading branch information
habdelra authored Jan 20, 2025
2 parents cc54e6e + d3f0987 commit 8ea6f45
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 15 deletions.
26 changes: 16 additions & 10 deletions packages/host/app/lib/current-run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,21 +284,27 @@ export class CurrentRun {
): Promise<string[]> {
log.debug(`discovering invalidations in dir ${url.href}`);
perfLog.debug(`discovering invalidations in dir ${url.href}`);
let ignoreStart = Date.now();
let ignorePatterns = await this.#reader.readFile(
new URL('.gitignore', url),
);
perfLog.debug(`time to get ignore rules ${Date.now() - ignoreStart} ms`);
if (ignorePatterns && ignorePatterns.content) {
this.ignoreMap.set(url.href, ignore().add(ignorePatterns.content));
this.#ignoreData[url.href] = ignorePatterns.content;
}

let mtimesStart = Date.now();
let filesystemMtimes = await this.#reader.mtimes();
perfLog.debug(
`time to get file system mtimes ${Date.now() - mtimesStart} ms`,
);

let ignoreFile = new URL('.gitignore', url).href;
// it costs about 10 sec to try to get the ignore file when it doesn't
// exist, so don't get it if it's not there.
if (filesystemMtimes[ignoreFile]) {
let ignoreStart = Date.now();
let ignorePatterns = await this.#reader.readFile(new URL(ignoreFile));
perfLog.debug(`time to get ignore rules ${Date.now() - ignoreStart} ms`);
if (ignorePatterns && ignorePatterns.content) {
this.ignoreMap.set(url.href, ignore().add(ignorePatterns.content));
this.#ignoreData[url.href] = ignorePatterns.content;
}
} else {
perfLog.debug(`skip getting the ignore file--there is nothing to ignore`);
}

let invalidationList: string[] = [];
let skipList: string[] = [];
for (let [url, lastModified] of Object.entries(filesystemMtimes)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
pristine_doc BLOB,
search_doc BLOB,
error_doc BLOB,
deps BLOB,
deps BLOB DEFAULT '[]',
types BLOB,
isolated_html TEXT,
indexed_at,
Expand All @@ -36,7 +36,7 @@
pristine_doc BLOB,
search_doc BLOB,
error_doc BLOB,
deps BLOB,
deps BLOB DEFAULT '[]',
types BLOB,
icon_html TEXT,
isolated_html TEXT,
Expand Down
25 changes: 25 additions & 0 deletions packages/postgres/migrations/1737128666066_deps-default-value.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
exports.up = (pgm) => {
pgm.alterColumn('boxel_index', 'deps', {
default: `[]`,
});
pgm.alterColumn('boxel_index_working', 'deps', {
default: `[]`,
});
pgm.createIndex('boxel_index', ['realm_url', 'type']);
pgm.createIndex('boxel_index_working', ['realm_url', 'type']);
pgm.sql(`UPDATE boxel_index SET deps = '[]'::jsonb WHERE deps IS NULL`);
pgm.sql(
`UPDATE boxel_index_working SET deps = '[]'::jsonb WHERE deps IS NULL`,
);
};

exports.down = (pgm) => {
pgm.dropIndex('boxel_index', ['realm_url', 'type']);
pgm.dropIndex('boxel_index_working', ['realm_url', 'type']);
pgm.alterColumn('boxel_index', 'deps', {
default: null,
});
pgm.alterColumn('boxel_index_working', 'deps', {
default: null,
});
};
7 changes: 7 additions & 0 deletions packages/postgres/scripts/convert-to-sqlite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ function createColumns(
if ('value' in constraint.expr) {
column.push('DEFAULT', String(constraint.expr.value));
break;
} else if (
constraint.expr.type === 'cast_operator_expr' &&
'expr' in constraint.expr &&
'text' in constraint.expr.expr
) {
column.push('DEFAULT', String(constraint.expr.expr.text));
break;
} else {
throw new Error(
`Don't know how to serialize default value constraint for expression type '${constraint.expr.type}'`,
Expand Down
17 changes: 14 additions & 3 deletions packages/runtime-common/index-writer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,8 @@ export class Batch {

async invalidate(url: URL): Promise<string[]> {
await this.ready;
let start = Date.now();
this.#perfLog.debug(`starting invalidation of ${url.href}`);
let alias = trimExecutableExtension(url).href;
let visited = new Set<string>();
let invalidations = [
Expand Down Expand Up @@ -447,6 +449,7 @@ export class Batch {
);

let names = flattenDeep(columns);
let insertStart = Date.now();
await this.#query([
'INSERT INTO boxel_index_working',
...addExplicitParens(separatedByCommas(columns)),
Expand All @@ -457,6 +460,15 @@ export class Batch {
'ON CONFLICT ON CONSTRAINT boxel_index_working_pkey DO UPDATE SET',
...separatedByCommas(names.map((name) => [`${name}=EXCLUDED.${name}`])),
] as Expression);
this.#perfLog.debug(
`inserted invalidated rows for ${url.href} in ${
Date.now() - insertStart
} ms`,
);

this.#perfLog.debug(
`completed invalidation of ${url.href} in ${Date.now() - start} ms`,
);

this.#invalidations = new Set([...this.#invalidations, ...invalidations]);
return invalidations;
Expand Down Expand Up @@ -492,7 +504,7 @@ export class Batch {
[
dbExpression({
sqlite: `deps_array_element =`,
pg: `COALESCE(i.deps, '[]'::jsonb) @>`,
pg: `i.deps @>`,
}),
param({ sqlite: resolvedPath, pg: `["${resolvedPath}"]` }),
],
Expand All @@ -503,7 +515,6 @@ export class Batch {
// realm invalidation
[`i.realm_url =`, param(this.realmURL.href)],
]),
'ORDER BY i.url COLLATE "POSIX"',
`LIMIT ${pageSize} OFFSET ${pageNumber * pageSize}`,
] as Expression)) as (Pick<BoxelIndexTable, 'url' | 'file_alias'> & {
type: 'instance' | 'module' | 'error';
Expand All @@ -514,7 +525,7 @@ export class Batch {
this.#perfLog.debug(
`time to determine items that reference ${resolvedPath} ${
Date.now() - start
} ms`,
} ms (page count=${pageNumber})`,
);
return results.map(({ url, file_alias, type }) => ({
url,
Expand Down

0 comments on commit 8ea6f45

Please sign in to comment.