Skip to content

Commit bfc6da4

Browse files
authored
Merge pull request #10372 from quarto-dev/sass-cache-cleanup
2 parents be2792d + a742831 commit bfc6da4

File tree

7 files changed

+59
-13
lines changed

7 files changed

+59
-13
lines changed

src/core/cleanup.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
/*
2-
* cleanup.ts
3-
*
4-
* Copyright (C) 2020-2022 Posit Software, PBC
5-
*
6-
*/
2+
* cleanup.ts
3+
*
4+
* Copyright (C) 2020-2022 Posit Software, PBC
5+
*/
76

87
import { info } from "../deno_ral/log.ts";
98

@@ -14,7 +13,9 @@ export function onCleanup(handler: VoidFunction) {
1413
}
1514

1615
export function exitWithCleanup(code: number) {
17-
for (const handler of cleanupHandlers) {
16+
// Not using cleanupHandlers.reverse() to not mutate the original array
17+
for (let i = cleanupHandlers.length - 1; i >= 0; i--) {
18+
const handler = cleanupHandlers[i];
1819
try {
1920
handler();
2021
} catch (error) {

src/core/sass.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,8 @@ export async function compileWithCache(
307307
const cacheDir = useSessionCache
308308
? join(temp.baseDir, "sass")
309309
: quartoCacheDir("sass");
310-
const cache = await sassCache(cacheDir);
310+
// when using quarto session cache, we ensure to cleanup the cache files at TempContext cleanup
311+
const cache = await sassCache(cacheDir, useSessionCache ? temp : undefined);
311312
return cache.getOrSet(input, loadPaths, temp, cacheIdentifier, compressed);
312313
} else {
313314
const outputFilePath = temp.createFile({ suffix: ".css" });

src/core/sass/cache.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { dartCompile } from "../dart-sass.ts";
1414
import { TempContext } from "../temp.ts";
1515
import { safeRemoveIfExists } from "../path.ts";
1616
import * as log from "../../deno_ral/log.ts";
17+
import { onCleanup } from "../cleanup.ts";
1718

1819
class SassCache {
1920
kv: Deno.Kv;
@@ -155,6 +156,21 @@ class SassCache {
155156
compressed,
156157
);
157158
}
159+
160+
// add a cleanup method to register a cleanup handler
161+
cleanup(temp: TempContext | undefined) {
162+
const registerCleanup = temp ? temp.onCleanup : onCleanup;
163+
registerCleanup(() => {
164+
try {
165+
this.kv.close();
166+
if (temp) safeRemoveIfExists(this.path);
167+
} catch (error) {
168+
log.info(
169+
`Error occurred during sass cache cleanup for ${this.path}: ${error}`,
170+
);
171+
}
172+
});
173+
}
158174
}
159175

160176
const currentSassCacheVersion = 1;
@@ -192,14 +208,20 @@ async function checkVersion(kv: Deno.Kv, path: string) {
192208
}
193209

194210
const _sassCache: Record<string, SassCache> = {};
195-
export async function sassCache(path: string): Promise<SassCache> {
211+
212+
export async function sassCache(
213+
path: string,
214+
temp: TempContext | undefined,
215+
): Promise<SassCache> {
196216
if (!_sassCache[path]) {
197217
log.debug(`Creating SassCache at ${path}`);
198218
ensureDirSync(path);
199219
const kvFile = join(path, "sass.kv");
200220
const kv = await Deno.openKv(kvFile);
201221
await checkVersion(kv, kvFile);
202222
_sassCache[path] = new SassCache(kv, path);
223+
// register cleanup for this cache
224+
_sassCache[path].cleanup(temp);
203225
}
204226
log.debug(`Returning SassCache at ${path}`);
205227
const result = _sassCache[path];

src/core/temp-types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ export interface TempContext {
99
createFile: (options?: Deno.MakeTempOptions) => string;
1010
createDir: (options?: Deno.MakeTempOptions) => string;
1111
cleanup: () => void;
12+
onCleanup: (handler: VoidFunction) => void;
1213
}

src/core/temp.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Copyright (C) 2020-2022 Posit Software, PBC
55
*/
66

7-
import { debug } from "../deno_ral/log.ts";
7+
import { debug, info } from "../deno_ral/log.ts";
88
import { join } from "../deno_ral/path.ts";
99
import { ensureDirSync, existsSync } from "fs/mod.ts";
1010
import { normalizePath, removeIfExists, safeRemoveIfExists } from "./path.ts";
@@ -53,11 +53,14 @@ export function globalTempContext() {
5353
return tempContext;
5454
}
5555

56-
export function createTempContext(options?: Deno.MakeTempOptions) {
56+
export function createTempContext(options?: Deno.MakeTempOptions): TempContext {
5757
let dir: string | undefined = Deno.makeTempDirSync({
5858
...options,
5959
dir: tempDir,
6060
});
61+
62+
const tempContextCleanupHandlers: VoidFunction[] = [];
63+
6164
return {
6265
baseDir: dir,
6366
createFile: (options?: Deno.MakeTempOptions) => {
@@ -68,10 +71,22 @@ export function createTempContext(options?: Deno.MakeTempOptions) {
6871
},
6972
cleanup: () => {
7073
if (dir) {
74+
// Not using .reverse() to not mutate the original array
75+
for (let i = tempContextCleanupHandlers.length - 1; i >= 0; i--) {
76+
const handler = tempContextCleanupHandlers[i];
77+
try {
78+
handler();
79+
} catch (error) {
80+
info("Error occurred during tempContext handler cleanup: " + error);
81+
}
82+
}
7183
safeRemoveIfExists(dir);
7284
dir = undefined;
7385
}
7486
},
87+
onCleanup(handler: VoidFunction) {
88+
tempContextCleanupHandlers.push(handler);
89+
},
7590
};
7691
}
7792

src/project/serve/serve.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@
66

77
import { info, warning } from "../../deno_ral/log.ts";
88
import { existsSync } from "fs/mod.ts";
9-
import { basename, dirname, extname, join, relative } from "../../deno_ral/path.ts";
9+
import {
10+
basename,
11+
dirname,
12+
extname,
13+
join,
14+
relative,
15+
} from "../../deno_ral/path.ts";
1016
import * as colors from "fmt/colors.ts";
1117

1218
import * as ld from "../../core/lodash.ts";
@@ -906,7 +912,7 @@ function acquirePreviewLock(project: ProjectContext) {
906912
// write our pid to the lockfile
907913
Deno.writeTextFileSync(lockfile, String(Deno.pid));
908914

909-
// rmeove the lockfile when we exit
915+
// remove the lockfile when we exit
910916
onCleanup(() => releasePreviewLock(project));
911917
}
912918

tests/verify.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export const noErrorsOrWarnings: Verify = {
111111
name: "No Errors or Warnings",
112112
verify: (outputs: ExecuteOutput[]) => {
113113
const isErrorOrWarning = (output: ExecuteOutput) => {
114-
return output.levelName.toLowerCase() === "warning" ||
114+
return output.levelName.toLowerCase() === "warn" ||
115115
output.levelName.toLowerCase() === "error";
116116
};
117117

0 commit comments

Comments
 (0)