Stream data sets through a Zowe SDK sidecar#6
Merged
Conversation
Probe every DSNSearchPath library in parallel per member, keeping the result from the earliest library in search order, and prefetch the distinct COPY members of each expansion level concurrently so slow per-member Zowe requests overlap. Concurrent zowe invocations are bounded to eight, and resolved members and failed lookups are both cached for the command. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjWnBCSp1WmbKwiWYGwKqK
Log the loaded config and search path, each zowe invocation with byte counts and durations, resolver decisions (which library won, cache hits, misses), the record shape, and the decoded record count. The debug logger writes to stderr only when --verbose is set, so JSON on stdout stays clean for piping. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjWnBCSp1WmbKwiWYGwKqK
Replace the one-zowe-CLI-process-per-data-set transport with an optional long-lived Node sidecar that resolves the user's existing Zowe configuration (team config, secure credential store, tokens) through the official Zowe SDK's ProfileInfo API and serves data set reads over the z/OSMF REST API. cq and the sidecar speak newline-delimited JSON over stdio, with multiplexed requests, base64-chunked streaming, and cancel for early exits, so records decode straight off the wire with no temporary file and copybook probes share one warm process. Select it with --sidecar 'node sidecar/zowe-sidecar.js' or the Sidecar config field; the zowe CLI remains the default transport behind a new zoweTransport seam. The sidecar owns credentials end to end; cq never sees them. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjWnBCSp1WmbKwiWYGwKqK
Standalone @zowe/imperative has no credential manager, so any Zowe team config with secure fields (the zowe CLI default) failed with 'Failed to initialize secure credential manager'. Depend on @zowe/secrets-for-zowe-sdk and pass its keyring to ProfileInfo through ProfileCredentials.defaultCredMgrWithKeytar — the same keyring the zowe CLI itself uses (macOS Keychain, Windows Credential Manager, libsecret). Plain-text configs keep working without the native module, and a failed store load now reports what to do about it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjWnBCSp1WmbKwiWYGwKqK
Remove the per-call zowe CLI wrapper: all DSN access now goes through the Zowe SDK sidecar, started lazily on first data set access so purely local runs never pay for it. The default command is cq-zowe-sidecar from PATH (npm install -g ./sidecar); the config file's sidecar field overrides it. With -max N and no -where filter, the download request carries the record count and length, and the sidecar asks z/OSMF for just those records via X-IBM-Record-Range in record mode. Each record's length prefix is validated against the layout's record length; any mismatch, partial trailer, or HTTP error on the ranged request transparently restarts the transfer as a plain binary stream (skipping bytes already delivered), so the bound can only save work, never change output. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjWnBCSp1WmbKwiWYGwKqK
The IBM z/OSMF reference confirms SSS,NNN offsets are 0-based, record mode prefixes are 4-byte big endian lengths excluding the prefix, and a range matching no records returns an exception rather than an empty response — verified end-to-end that the fallback turns that exception into an empty result instead of an error. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjWnBCSp1WmbKwiWYGwKqK
process.stdout.write() never blocks: when the pipe to cq is full it queues the write on the heap and returns false, and the z/OSMF socket kept delivering, so a consumer slower than the mainframe (cq piped into a throttled jq, a pager, a slow disk) ballooned the sidecar's memory with the entire un-consumed remainder of the data set. Pause the HTTP response whenever a frame write reports a full pipe and resume it on stdout drain, in both the plain and record-ranged streaming paths. Measured with a 160MB data set against a rate-limited consumer: peak sidecar RSS drops from 666MB (scaling with data set size) to a flat 143MB one-burst plateau that holds at 4x the data. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjWnBCSp1WmbKwiWYGwKqK
Tannex
commented
Jul 14, 2026
Tannex
commented
Jul 14, 2026
Tannex
commented
Jul 14, 2026
Tannex
commented
Jul 14, 2026
Tannex
commented
Jul 14, 2026
Tannex
commented
Jul 14, 2026
Tannex
commented
Jul 14, 2026
Tannex
commented
Jul 14, 2026
Tannex
commented
Jul 14, 2026
Tannex
commented
Jul 14, 2026
- Fail reads on a closed sidecar stream with io.ErrClosedPipe instead of blocking forever once the buffered bytes are consumed - Resolve COPY members as soon as the winning library is known and cancel later in-flight probes (fetchCopybook now takes a context), so a slow irrelevant library never delays or blocks an earlier match - Parse quoted executables and arguments in the sidecar command through splitCommandSpec, shared with the config editor spec - Give ZOWE_OPT_* environment variables the zowe CLI's precedence over profile properties, and honor ZOWE_OPT_ZOSMF_PROFILE profile selection - Reject Basic-auth profiles that have a user but no password up front instead of sending "user:undefined" - Bound non-200 error body buffering to a 16 KiB prefix with a timeout - Fall back to a plain transfer when a ranged request or response fails mid-stream, resuming after the records already delivered - Require Node >=20.9.0, matching the locked @zowe/imperative engine Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014CmkgLDN4iT6z2B23YuVQf
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
Replaces the per-call `zowe` CLI wrapper with a small Node sidecar built on the official Zowe SDK, and layers cq's DSN access on top of it:
The zowe CLI wrapping path is fully removed. The sidecar starts lazily on first DSN access (`cq-zowe-sidecar` from PATH by default, `"sidecar"` in config.json to override), so purely local runs don't need it.
Testing
🤖 Generated with Claude Code
https://claude.ai/code/session_01UjWnBCSp1WmbKwiWYGwKqK