Repository navigation
Streaming terminals sensors().stream() and frus().stream() (#235) - #238
Conversation
SensorsRequest.stream() and FrusRequest.stream() yield each sensor or FRU as soon as it is read, as a lazy sequential Stream to close with try-with-resources, like winrm-java's WqlRequest.stream(). The SDR repository is walked before the stream is returned; each element is then read as an operation of the client of its own, so the request timeout is an inactivity timeout, the operations of other threads run between two elements, an abandoned stream blocks nothing, and a session lost while an element is read is reopened and that element read again without the ones already yielded. onSkippedRecord(Consumer<SkippedRecord>) on both requests reports the records the walk skipped before the first element; execute() calls it too. execute() and stream() share one implementation: the sensor walk becomes a cursor (SensorCursor) and FruReader a cursor that reads one FRU per next(). ipmicli sensors --json and ipmicli fru print each sensor or FRU as it is read; the sensors table still collects them for its column widths. Documents the new terminal (sensors, FRU inventory, timeouts, CLI, upgrading, README) and fixes a Latin-1 degree sign in sensors.md. Closes #235 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f4ff313db6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Stream.close() does not invalidate an iterator already obtained from the stream: its next() still ran the cursor and sent a command after the close. The close handler now marks the spliterator ended, as the Javadoc promises. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ipmicli sensors collected every sensor before printing its table, to size the columns on their widest value, so the table appeared at once while sensors --json and fru already printed as they read. The table now streams too: fixed widths (16 for the name, 22 for the type, 9 for the reading, 12 for the unit; --long adds 6 for the number, 24 for the entity, 15 for the status and 7 per threshold), a wider cell pushing the rest of its row, each row flushed as its sensor is read. row() lays out one line; table() keeps sizing the other tables. Golden files and the CLI and upgrading pages follow. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f4780fc82b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The spliterator behind stream() inherited a trySplit() that reads up to 1024 elements ahead when the stream is made parallel, so stream().parallel().limit(1) could read every sensor of a small repository: it now returns null, and the source stays sequential. FruReader read FRU 0 of the BMC before the first FRU, whatever the order of the records, so frus().stream().limit(1) paid for it even when a PSU came first: the areas are read when a record of the system board is reached, or after the pass for the fallback. The FRUs come in the same order as before (checked on a Lenovo TSM and an iLO 5). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cec5567591
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
A caller that gives up an element at the timeout of its request cancels the task with an interrupt; Link.attempt() turned it into an IpmiClientException that readSensor() and FruReader.inventory() absorbed as a problem, so the cursor advanced past an element whose result the cancelled future discarded, and the next operation of the stream skipped it. Each read now fails when the worker was interrupted, and the cursor keeps the element for the next operation. The sentinel read after the last element went through run() with a session, so a session lost meanwhile was reopened to find nothing, and a failed reopening turned a complete traversal into an exception. The cursors tell, without a command, whether an element may remain, and the stream ends on the last element. Checkstyle warnings now fail the build (violationSeverity=warning), as the GitHub check-run only reports them: the five TODO comments left by Verax in SensorRecord and FruRecord are removed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Closes #235.
What
SensorsRequest.stream()andFrusRequest.stream(): a lazy, sequential, orderedStream(Java 8StreamSupportover aSpliterator, as in winrm-java) that yields each sensor or FRU as soon as it is read, in the order ofexecute(). The selection (types(),names(),ids()) applies as before: an unselected sensor costs no round trip.onSkippedRecord(Consumer<SkippedRecord>)on both requests: the SDR records the walk skipped are given to the consumer before the first element (the walk happens whenstream()is called);execute()calls it too and still lists them inskippedRecords().execute()keeps its result type and shares one implementation withstream(): the sensor walk becomes a cursor (SensorCursor), andFruReaderbecomes a cursor that reads one FRU pernext().ipmicli sensorsandipmicli fruprint each sensor or FRU as it is read; thesensorstable moves to fixed column widths for that (a wider cell pushes the rest of its row), which changes its golden files and is noted as a behavior change inupgrading.md.violationSeverity=warning), as the GitHub check-run only reports them as neutral; the five TODO comments left by Verax inSensorRecordandFruRecordare removed.The points the issue asked to settle
stream()andtimeout(Duration).execute()keeps its overall deadline.close()) run in between, and an abandoned stream blocks nothing. Closing early sends no further command.silentOwners/silentControllerssets live in the cursor, across the whole stream.Tests
Three fake-BMC tests: elements arrive before the walk ends and a closed stream reads no more;
limit(1)reads one sensor; an unselected sensor costs no command; a session lost mid-stream is replaced without a duplicate or lost element (sensors and FRUs);execute()unchanged.mvn verify sitepasses (412 tests, checkstyle/PMD/CPD/SpotBugs gates clean).Also fixes a Latin-1 degree sign in
sensors.mdnoticed on the way.🤖 Generated with Claude Code