Skip to content

Commit

Permalink
Improve clarity a bit more.
Browse files Browse the repository at this point in the history
  • Loading branch information
rictic committed Sep 5, 2023
1 parent 42b48c0 commit fcba1f8
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 165 deletions.
2 changes: 1 addition & 1 deletion src/execution/standard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ export class StandardScriptExecution extends BaseExecutionWithCommand<StandardSc
type: 'info',
detail: 'running',
notFreshReason,
executionRequestedReason: executionRequestedReason,
executionRequestedReason,
});

const child = new ScriptChildProcess(
Expand Down
13 changes: 0 additions & 13 deletions src/fingerprint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,19 +295,6 @@ export class Fingerprint {
return this.string === other.string;
}

requiresRebuild(previous: Fingerprint | undefined): boolean {
// If we're not fully tracked, we always need to rebuild.
if (!this.data.fullyTracked) {
return true;
}
// If we don't have a previous fingerprint, we need to rebuild.
if (previous === undefined) {
return true;
}
// Otherwise, we need to rebuild if the fingerprint changed.
return !this.equal(previous);
}

difference(previous: Fingerprint): FingerprintDifference | undefined {
// Do a string comparison first, because it's much faster than
// checking field by field;
Expand Down
258 changes: 125 additions & 133 deletions src/logging/default-logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@
import * as pathlib from 'path';
import {unreachable} from '../util/unreachable.js';

import type {Event} from '../event.js';
import type {
Event,
FingerprintDifference,
NeedsToRunReason,
ServiceStoppedReason,
} from '../event.js';
import type {Logger} from './logger.js';
import {
stringToScriptReference,
Expand Down Expand Up @@ -315,138 +320,7 @@ export class DefaultLogger implements Logger {
break;
}
case 'service-stopped': {
let reason: string;
switch (event.reason.name) {
default: {
const never: never = event.reason;
throw new Error(
`Unknown service stop reason: ${inspect(never)}`,
);
}
case 'all consumers of the service are done':
case 'the depgraph changed, service is no longer needed':
case 'the run was aborted':
case 'unknown':
reason = event.reason.name;
break;
case 'restart': {
const restartReason = event.reason;
switch (restartReason.reason.name) {
default: {
const never: never = restartReason.reason;
throw new Error(
`Unknown restart reason: ${inspect(never)}`,
);
}
case 'not-fully-tracked': {
const notFullyTrackedReason = restartReason.reason.reason;
switch (notFullyTrackedReason.name) {
default: {
const never: never = notFullyTrackedReason;
throw new Error(
`Unknown not-fully-tracked reason: ${inspect(never)}`,
);
}
case 'dependency not fully tracked': {
reason = `the service depends on ${labelForScript(
this.rootPackageDir,
stringToScriptReference(
notFullyTrackedReason.dependency,
),
)}`;
break;
}
case 'no files field': {
throw new Error(
'Internal error: a service is tracked even without a files field',
);
}
case 'no output field': {
throw new Error(
'Internal error: a service never has output',
);
}
}
break;
}
case 'no-previous-fingerprint': {
throw new Error(
'Internal error: could not find a previous fingerprint, so we restarted the server?',
);
}
case 'fingerprints-differed': {
const difference = restartReason.reason.difference;
switch (difference.name) {
default: {
const never: never = difference;
throw new Error(
`Unknown not-fully-tracked reason: ${inspect(never)}`,
);
}
case 'config': {
reason = `config field ${
difference.field
} changed from ${inspect(
difference.previous,
)} to ${inspect(difference.current)}`;
break;
}
case 'environment': {
reason = `the ${
difference.field
} of the environment changed from ${inspect(
difference.previous,
)} to ${inspect(difference.current)}`;
break;
}
case 'dependency added': {
reason = `a dependency was added: [${labelForScript(
this.rootPackageDir,
stringToScriptReference(difference.script),
)}]`;
break;
}
case 'dependency removed': {
reason = `a dependency was removed: [${labelForScript(
this.rootPackageDir,
stringToScriptReference(difference.script),
)}]`;
break;
}
case 'dependency changed': {
reason = `a dependency changed: [${labelForScript(
this.rootPackageDir,
stringToScriptReference(difference.script),
)}]`;
break;
}
case 'file added': {
reason = `a file was added: ${pathlib.relative(
this.rootPackageDir,
difference.path,
)}`;
break;
}
case 'file removed': {
reason = `a file was removed: ${pathlib.relative(
this.rootPackageDir,
difference.path,
)}`;
break;
}
case 'file changed': {
reason = `a file was changed: ${pathlib.relative(
this.rootPackageDir,
difference.path,
)}`;
break;
}
}
}
}
break;
}
}
const reason = this.#explainServiceStopped(event.reason);
console.log(`⬇️${prefix} Service stopped because ${reason}`);
if (event.failure !== undefined) {
// Use console.group to indent
Expand All @@ -466,6 +340,124 @@ export class DefaultLogger implements Logger {
}
}

#explainServiceStopped(reason: ServiceStoppedReason): string {
switch (reason.name) {
default: {
const never: never = reason;
throw new Error(`Unknown service stop reason: ${inspect(never)}`);
}
case 'all consumers of the service are done':
case 'the depgraph changed, service is no longer needed':
case 'the run was aborted':
case 'unknown':
return reason.name;
case 'restart': {
return this.#explainServiceRestart(reason.reason);
}
}
}

#explainServiceRestart(reason: NeedsToRunReason): string {
switch (reason.name) {
default: {
const never: never = reason;
throw new Error(`Unknown restart reason: ${inspect(never)}`);
}
case 'not-fully-tracked': {
const notFullyTrackedReason = reason.reason;
switch (notFullyTrackedReason.name) {
default: {
const never: never = notFullyTrackedReason;
throw new Error(
`Unknown not-fully-tracked reason: ${inspect(never)}`,
);
}
case 'dependency not fully tracked': {
return `the service depends on [${labelForScript(
this.rootPackageDir,
stringToScriptReference(notFullyTrackedReason.dependency),
)}] which must always be run`;
}
case 'no files field': {
throw new Error(
'Internal error: a service is tracked even without a files field',
);
}
case 'no output field': {
throw new Error('Internal error: a service never has output');
}
}
}
case 'no-previous-fingerprint': {
throw new Error(
'Internal error: could not find a previous fingerprint, so we restarted the server?',
);
}
case 'fingerprints-differed': {
return this.#explainServiceFingerprintDifference(reason.difference);
}
}
}

#explainServiceFingerprintDifference(
difference: FingerprintDifference,
): string {
switch (difference.name) {
default: {
const never: never = difference;
throw new Error(`Unknown not-fully-tracked reason: ${inspect(never)}`);
}
case 'config': {
return `config field ${difference.field} changed from ${inspect(
difference.previous,
)} to ${inspect(difference.current)}`;
}
case 'environment': {
return `the ${
difference.field
} of the environment changed from ${inspect(
difference.previous,
)} to ${inspect(difference.current)}`;
}
case 'dependency added': {
return `a dependency was added: [${labelForScript(
this.rootPackageDir,
stringToScriptReference(difference.script),
)}]`;
}
case 'dependency removed': {
return `a dependency was removed: [${labelForScript(
this.rootPackageDir,
stringToScriptReference(difference.script),
)}]`;
}
case 'dependency changed': {
return `a dependency changed: [${labelForScript(
this.rootPackageDir,
stringToScriptReference(difference.script),
)}]`;
}
case 'file added': {
return `a file was added: ${pathlib.relative(
this.rootPackageDir,
difference.path,
)}`;
}
case 'file removed': {
return `a file was removed: ${pathlib.relative(
this.rootPackageDir,
difference.path,
)}`;
}
case 'file changed': {
return `a file was changed: ${pathlib.relative(
this.rootPackageDir,
difference.path,
)}`;
}
}
}

printMetrics(): void {
// printMetrics() not used in default-logger.
}
Expand Down
Loading

0 comments on commit fcba1f8

Please sign in to comment.