Skip to content

[BUG] eliminate redundant gRPC engine version fetch in Worker.start() #4272

Description

@chandan-1427

Describe the issue
When Worker.start() is called on the non-legacy path, it makes two separate gRPC calls to fetch the engine version — one inside isLegacyEngine() and a second explicit call to fetchEngineVersion() immediately after. Both calls fetch identical data. The result from the first call is discarded, and the second call is used for eviction support checking and setting _internal.engineVersion.

Environment

  • SDK: TypeScript (v1 worker, client/worker/worker.ts)
  • Engine: Cloud or Self-hosted (any version that supports GetVersion)

Expected behavior
The engine version should be fetched once per Worker.start() invocation and the result reused across both the legacy engine check and eviction support check.

Code to Reproduce, Logs, or Screenshots

In client/worker/worker.ts:

async start() {
  // Call 1: fetchEngineVersion is called internally inside isLegacyEngine
  if (await isLegacyEngine(this._v1)) {
    ...
    return this._legacyWorker.start();
  }

  // Call 2: fetchEngineVersion called again immediately after
  const engineVersion = await fetchEngineVersion(this._v1).catch(() => undefined);
  this._checkEvictionSupport(engineVersion);
  this._internal.engineVersion = engineVersion;

  return this._internal.start();
}

In client/worker/deprecated/legacy-worker.ts, isLegacyEngine internally calls fetchEngineVersion:

export async function isLegacyEngine(v1: HatchetClient): Promise<boolean> {
  const version = await fetchEngineVersion(v1).catch(...);
  if (!version || semverLessThan(version, MinEngineVersion.SLOT_CONFIG)) {
    ...
    return true;
  }
  return false;
}

The fix is to fetch once in start(), inline the legacy check, and delete isLegacyEngine:

async start() {
  const engineVersion = await fetchEngineVersion(this._v1).catch(() => undefined);

  if (!engineVersion || semverLessThan(engineVersion, MinEngineVersion.SLOT_CONFIG)) {
    const legacyConfig: CreateWorkerOpts = { ...this.config, ... };
    this._legacyWorker = await LegacyDualWorker.create(this._v1, this.name, legacyConfig);
    return this._legacyWorker.start();
  }

  this._checkEvictionSupport(engineVersion);
  this._internal.engineVersion = engineVersion;
  return this._internal.start();
}

Additional context
Three files need to change: client/worker/worker.ts (inline the fetch + legacy check), client/worker/deprecated/legacy-worker.ts and client/worker/deprecated/index.ts (delete isLegacyEngine as it becomes dead code). fetchEngineVersion itself remains unchanged.


🤖 AI Disclosure
  • I acknowledge that an LLM was used in the creation of this Issue, in accordance with Hatchet's AI_POLICY.md.
  • Details: Bug identified and diagnosed via Claude (Anthropic) during a code review of worker.ts and deprecated/index.ts. Fix verified manually by tracing the call chain across both files.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions