Skip to content

Commit

Permalink
Fix/timeout progress combo (#900)
Browse files Browse the repository at this point in the history
Add support for disabling the use of data being received on the stdOut, stdErr or both streams of the underlying git process as a reason to reset the block timeout of the timeout plugin.
  • Loading branch information
steveukx authored Mar 4, 2023
1 parent c5ac28a commit a63cfc2
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/eight-apes-beam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'simple-git': minor
---

Timeout plugin can now be configured to ignore data on either stdOut or stdErr in the git process when determining whether to kill the spawned process.
53 changes: 52 additions & 1 deletion docs/PLUGIN-TIMEOUT.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ To handle the case where the underlying `git` processes appear to hang, configur
import { simpleGit, GitPluginError, SimpleGit, SimpleGitProgressEvent } from 'simple-git';

const git: SimpleGit = simpleGit({
baseDir: '/some/path',
timeout: {
block: 2000,
},
Expand All @@ -25,3 +24,55 @@ catch (err) {
}
}
```

## Task Timeouts and Progress Events

The default behaviour of the timeout plugin is to listen for data being received on both the
`stdOut` and `stdErr` streams from the `git` child process.

When using the `progress` plugin, `git` will be streaming regular progress updates to `stdErr`,
so you may see that the timeout is never reached and `simple-git` patiently waits for `git` to
finish whatever it is doing.

Configure this with the optional `stdOut` and `stdErr` properties of the `timeout` plugin
configuration:

```typescript
import { simpleGit, SimpleGit } from "simple-git";

const git: SimpleGit = simpleGit({
progress({method, stage, progress}) {
console.log(`git.${method} ${stage} stage ${progress}% complete`);
},
timeout: {
block: 2000,
stdOut: true, // default behaviour, resets the 2s timer every time data arrives on stdOut
stdErr: false // custom behaviour, ignore the progress events being written to stdErr
}
});

```

## Absolute or Block Timeouts

The timeout plugin will reset its timers whenever data is received meaning the plugin will
only kill processes that appear to be hanging and allow intentionally long-running processes
to continue uninterrupted.

To change this default behaviour so that the plugin kills all processes after the supplied
timeout, configure it so the plugin doesn't listen for data updates by supplying the optional
`stdOut` and `stdErr` properties of the `timeout` plugin configuration:

```typescript
import { simpleGit, SimpleGit } from "simple-git";

// create a simple-git instance that kills any process after 5s
// whether it's still receiving data or not:
const git: SimpleGit = simpleGit({
timeout: {
block: 5000,
stdOut: false,
stdErr: false
}
});
```
6 changes: 4 additions & 2 deletions simple-git/src/lib/plugins/timout-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { GitPluginError } from '../errors/git-plugin-error';

export function timeoutPlugin({
block,
stdErr = true,
stdOut = true,
}: Exclude<SimpleGitOptions['timeout'], undefined>): SimpleGitPlugin<'spawn.after'> | void {
if (block > 0) {
return {
Expand All @@ -30,8 +32,8 @@ export function timeoutPlugin({
context.kill(new GitPluginError(undefined, 'timeout', `block timeout reached`));
}

context.spawned.stdout?.on('data', wait);
context.spawned.stderr?.on('data', wait);
stdOut && context.spawned.stdout?.on('data', wait);
stdErr && context.spawned.stderr?.on('data', wait);
context.spawned.on('exit', stop);
context.spawned.on('close', stop);

Expand Down
12 changes: 12 additions & 0 deletions simple-git/src/lib/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,18 @@ export interface SimpleGitPluginConfig {
* content on the stdOut/stdErr streams before forcibly closing the git process.
*/
block: number;

/**
* Reset timeout plugin after receiving data on `stdErr` - set to `false` to ignore
* `stdErr` content when determining whether to kill the process (defaults to `true`).
*/
stdErr?: boolean;

/**
* Reset timeout plugin after receiving data on `stdOut` - set to `false` to ignore
* `stdOut` content when determining whether to kill the process (defaults to `true`).
*/
stdOut?: boolean;
};

spawnOptions: Pick<SpawnOptions, 'uid' | 'gid'>;
Expand Down

0 comments on commit a63cfc2

Please sign in to comment.