-
Notifications
You must be signed in to change notification settings - Fork 97
Add async contexts, hierarchical cleanup, and log injection #305
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
Open
haggholm
wants to merge
8
commits into
raszi:master
Choose a base branch
from
hightouchio:petter/async-context
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 2 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
6bca69a
impl with async context (experimental)
haggholm ce1c332
Improvement to logging and cleanup
haggholm b87bc5f
Minor fixes
haggholm efd5095
Revert temp change to debug linking issues
haggholm 1795f95
Use fs.rm() over deprecated rmdir() for recursive cleanup
haggholm de51a39
Ignore errors on ENOENT for cleanup
haggholm a7d9b99
Add test for nested dir context
haggholm 52aa986
Check size delta before vs. after hierarchical GC for approximate cle…
haggholm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,303 @@ | ||
| // Copied and modified from definitely-typed, which is also MIT licensed. | ||
|
|
||
| // Type definitions for tmp 0.2 | ||
| // Project: https://github.com/raszi/node-tmp | ||
| // Definitions by: Jared Klopper <https://github.com/optical> | ||
| // Gyusun Yeom <https://github.com/Perlmint> | ||
| // Alan Plum <https://github.com/pluma> | ||
| // Carsten Klein <https://github.com/silkentrance> | ||
| // BendingBender <https://github.com/bendingbender> | ||
| // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped | ||
|
|
||
| export interface TmpNameOptions { | ||
| /** | ||
| * The optional temporary directory that must be relative to the system's default | ||
| * temporary directory. Absolute paths are fine as long as they point to a | ||
| * location under the system's default temporary directory. Any directories along | ||
| * the so specified path must exist, otherwise a `ENOENT` error will be thrown | ||
| * upon access, as tmp will not check the availability of the path, nor will it | ||
| * establish the requested path for you. | ||
| */ | ||
| dir?: string | undefined; | ||
| /** | ||
| * A fixed name that overrides random name generation, the name must | ||
| * be relative and must not contain path segments. | ||
| */ | ||
| name?: string | undefined; | ||
| /** | ||
| * The optional prefix. | ||
| * @default 'tmp' | ||
| */ | ||
| prefix?: string | undefined; | ||
| /** | ||
| * The optional postfix. | ||
| * @default '' | ||
| */ | ||
| postfix?: string | undefined; | ||
| /** | ||
| * [`mkstemp`](http://www.kernel.org/doc/man-pages/online/pages/man3/mkstemp.3.html) | ||
| * like filename template, no default, must include `XXXXXX` once for random name generation, | ||
| * e.g. `'foo-bar-XXXXXX'`. | ||
| */ | ||
| template?: string | undefined; | ||
| /** | ||
| * Allows you to override the system's root tmp directory. | ||
| */ | ||
| tmpdir?: string | undefined; | ||
| /** | ||
| * How many times should the function try to get a unique filename before giving up. | ||
| * @default 3 | ||
| */ | ||
| tries?: number | undefined; | ||
| } | ||
|
|
||
| export interface FileOptions extends TmpNameOptions { | ||
| /** | ||
| * Detaches the file descriptor, caller is responsible for closing the file, `tmp` will no | ||
| * longer try closing the file during garbage collection. | ||
| * @default false | ||
| */ | ||
| detachDescriptor?: boolean | undefined; | ||
| /** | ||
| * Discards the file descriptor (closes file, fd is -1), `tmp` will no longer try closing | ||
| * the file during garbage collection. | ||
| * @default false | ||
| */ | ||
| discardDescriptor?: boolean | undefined; | ||
| /** | ||
| * Signals that the temporary file or directory should not be deleted on exit | ||
| * | ||
| * - In order to clean up, you will have to call the provided `cleanupCallback` function manually. | ||
| * | ||
| * @default false | ||
| */ | ||
| keep?: boolean | undefined; | ||
| /** | ||
| * The file mode to create with. | ||
| * @default 0o600 | ||
| */ | ||
| mode?: number | undefined; | ||
| } | ||
|
|
||
| export interface FileOptionsDiscardFd extends FileOptions { | ||
| discardDescriptor: true; | ||
| } | ||
|
|
||
| export interface DirOptions extends TmpNameOptions { | ||
| /** | ||
| * Signals that the temporary file or directory should not be deleted on exit | ||
| * | ||
| * - In order to clean up, you will have to call the provided `cleanupCallback` function manually. | ||
| * | ||
| * @default false | ||
| */ | ||
| keep?: boolean | undefined; | ||
| /** | ||
| * The file mode to create with. | ||
| * @default 0o700 | ||
| */ | ||
| mode?: number | undefined; | ||
| /** | ||
| * Recursively removes the created temporary directory, even when it's not empty. | ||
| * @default false | ||
| */ | ||
| unsafeCleanup?: boolean | undefined; | ||
| } | ||
|
|
||
| export interface FileResult { | ||
| name: string; | ||
| fd: number; | ||
| removeCallback: () => void; | ||
| } | ||
|
|
||
| export type FileResultNoFd = Omit<FileResult, 'fd'>; | ||
|
|
||
| export interface DirResult { | ||
| name: string; | ||
| removeCallback: () => void; | ||
| } | ||
|
|
||
| export type FileCallback = (err: Error | null, name: string, fd: number, removeCallback: () => void) => void; | ||
| export type FileCallbackNoFd = (err: Error | null, name: string, fd: undefined, removeCallback: () => void) => void; | ||
|
|
||
| export type DirCallback = (err: Error | null, name: string, removeCallback: () => void) => void; | ||
|
|
||
| export type TmpNameCallback = (err: Error | null, name: string) => void; | ||
|
|
||
| type LogFn = | ||
| | ((msg: string) => void) | ||
| | ((logData: Record<string, unknown>, msg: string) => void); | ||
| export type Logger = { | ||
| debug: LogFn, | ||
| info: LogFn, | ||
| warn: LogFn, | ||
| error: LogFn, | ||
| }; | ||
|
|
||
| export const tmpdir: string; | ||
|
|
||
| /** | ||
| * Asynchronous file creation. | ||
| * | ||
| * Simple temporary file creation, the file will be closed and unlinked on process exit. | ||
| * | ||
| * @example | ||
| * import * as tmp from 'tmp'; | ||
| * | ||
| * tmp.file((err, path, fd, cleanupCallback) => { | ||
| * if (err) throw err; | ||
| * | ||
| * console.log('File: ', path); | ||
| * console.log('Filedescriptor: ', fd); | ||
| * | ||
| * // If we don't need the file anymore we could manually call the cleanupCallback | ||
| * // But that is not necessary if we didn't pass the keep option because the library | ||
| * // will clean after itself. | ||
| * cleanupCallback(); | ||
| * }); | ||
| */ | ||
| export function file(options: FileOptionsDiscardFd, cb: FileCallbackNoFd): void; | ||
| export function file(options: FileOptions, cb: FileCallback): void; | ||
| export function file(cb: FileCallback): void; | ||
|
|
||
| /** | ||
| * Synchronous file creation. | ||
| * | ||
| * Simple synchronous temporary file creation, the file will be closed and unlinked on process exit. | ||
| * | ||
| * @example | ||
| * import * as tmp from 'tmp'; | ||
| * | ||
| * const tmpobj = tmp.fileSync(); | ||
| * console.log('File: ', tmpobj.name); | ||
| * console.log('Filedescriptor: ', tmpobj.fd); | ||
| * | ||
| * // If we don't need the file anymore we could manually call the removeCallback | ||
| * // But that is not necessary if we didn't pass the keep option because the library | ||
| * // will clean after itself. | ||
| * tmpobj.removeCallback(); | ||
| */ | ||
| export function fileSync(options: FileOptionsDiscardFd): FileResultNoFd; | ||
| export function fileSync(options?: FileOptions): FileResult; | ||
|
|
||
| /** | ||
| * Asynchronous directory creation. | ||
| * | ||
| * Simple temporary directory creation, it will be removed on process exit. | ||
| * | ||
| * If the directory still contains items on process exit, then it won't be removed. | ||
| * | ||
| * @example | ||
| * import * as tmp from 'tmp'; | ||
| * | ||
| * tmp.dir((err, path, cleanupCallback) => { | ||
| * if (err) throw err; | ||
| * | ||
| * console.log('Dir: ', path); | ||
| * | ||
| * // Manual cleanup | ||
| * cleanupCallback(); | ||
| * }); | ||
| */ | ||
| export function dir(options: DirOptions, cb: DirCallback): void; | ||
| export function dir(cb: DirCallback): void; | ||
|
|
||
| /** | ||
| * Synchronous directory creation. | ||
| * | ||
| * Simple synchronous temporary directory creation, it will be removed on process exit. | ||
| * | ||
| * If the directory still contains items on process exit, then it won't be removed. | ||
| * | ||
| * @example | ||
| * import * as tmp from 'tmp'; | ||
| * | ||
| * const tmpobj = tmp.dirSync(); | ||
| * console.log('Dir: ', tmpobj.name); | ||
| * // Manual cleanup | ||
| * tmpobj.removeCallback(); | ||
| */ | ||
| export function dirSync(options?: DirOptions): DirResult; | ||
|
|
||
| /** | ||
| * Asynchronous filename generation. | ||
| * | ||
| * Generates a unique filename in the specified directory. | ||
| * | ||
| * @example | ||
| * import * as tmp from 'tmp'; | ||
| * | ||
| * tmp.tmpName((err, path) => { | ||
| * if (err) throw err; | ||
| * | ||
| * console.log('Created temporary filename: ', path); | ||
| * }); | ||
| */ | ||
| export function tmpName(options: TmpNameOptions, cb: TmpNameCallback): void; | ||
| export function tmpName(cb: TmpNameCallback): void; | ||
|
|
||
| /** | ||
| * Synchronous filename generation. | ||
| * | ||
| * Synchronously generates a unique filename in the specified directory. | ||
| * | ||
| * @example | ||
| * import * as tmp from 'tmp'; | ||
| * | ||
| * const name = tmp.tmpNameSync(); | ||
| * console.log('Created temporary filename: ', name); | ||
| */ | ||
| export function tmpNameSync(options?: TmpNameOptions): string; | ||
|
|
||
| /** | ||
| * Graceful cleanup. | ||
| * | ||
| * If graceful cleanup is set, `tmp` will remove all controlled temporary objects on process exit, | ||
| * otherwise the temporary objects will remain in place, waiting to be cleaned up on system | ||
| * restart or otherwise scheduled temporary object removal. | ||
| * | ||
| * @example | ||
| * import * as tmp from 'tmp'; | ||
| * | ||
| * tmp.setGracefulCleanup(); | ||
| */ | ||
| export function setGracefulCleanup(): void; | ||
|
|
||
|
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. New stuff below: |
||
| /** | ||
| * Specify a custom logger for debug output during GC. | ||
| */ | ||
| export function setLogger(logger: Logger): void; | ||
|
|
||
| /** | ||
| * Run a function in an async context where all tmpdir parameters, | ||
| * unless explicitly set to absolute paths, are automatically | ||
| * prepended with a subdirectory. This directory may be a path component | ||
| * or an absolute path, but it should always be nested under the OS | ||
| * temp directory. | ||
| * | ||
| * Subdirectories are created automatically. | ||
| * | ||
| * @param dir Subdirectory name. This is used literally, not as a prefix | ||
| * or postfix to random components. | ||
| * @param fn Function to run in context. Called with a cleanup function | ||
| * to purge the directory on completion. | ||
| * @param [options] | ||
| * @param [options.cleanup] If truthy, the subdirectory will be deleted | ||
| * when the function settles. Use with caution as it may delete files | ||
| * still in use. | ||
| * @param [options.logTags] If provided, these will be passed as the first | ||
| * parameter to logger calls during cleanup. | ||
| */ | ||
| export function withSubdir<T>( | ||
| dir: string, | ||
| fn: (cleanupFn: () => Promise<void>) => Promise<T>, | ||
| options?: { cleanup?: boolean, logTags?: Record<string, unknown> } | ||
| ): Promise<T>; | ||
|
|
||
| /** | ||
| * Explicitly invoke the garbage collection used by graceful cleanup. | ||
| * | ||
| * This should be used advisedly, as it may delete files still in use. | ||
| * Intended usage is at the top level between processing requests. | ||
| */ | ||
| export function gc(): void; | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Changes noted below.