§5 startup validation, §7 logging, §8 pre-flight#7
Closed
MarketDataDev03 wants to merge 2 commits into
Closed
Conversation
|
The author of this PR, MarketDataDev03, is not an activated member of this organization on Codecov. |
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.
Spec quick wins — §5 startup validation, §7 logging, §8 pre-flight
Wires up three spec-mandated behaviors that the previous PRs had left as seams:
/user/startup validation,MARKETDATA_LOGGING_LEVELhonoring + spec-shaped log format, and the pre-flight rate-limit check. All three were small (~150 LOC of prod) and ergonomically grouped — same constructor, same Configuration cascade, no architectural overlap with the retry work.Before this PR, the
MarketDataClientconstructors (both no-arg and 4-arg withvalidateOnStartup=true) were field-only: assign final fields, emit one INFO log line, return. No I/O, no blocking, no thrown exceptions.After this PR, when
validateOnStartup=true(the default) and the client is not in demo mode, the constructor performs a synchronousGET /user/call. That changes the constructor's contract in three ways:AuthenticationError(401),NetworkError(connection failure / timeout)baseUrlThis is mandated by spec §5 ("Fail fast on invalid tokens") and aligns with the Python SDK. But existing consumer code that assumed construction couldn't fail will see new failure modes after upgrading.
Migration guide for consumers
validateOnStartup=false. The first authenticated request will still fail withAuthenticationErrorif the token is bad — just lazily instead of eagerly.Migration guide for the SDK's own test suite
All unit tests that construct
MarketDataClientwith the default URL must passvalidateOnStartup=false, otherwise they reachapi.marketdata.appover the network. Anything that genuinely needs the live-API smoke goes tosrc/integrationTest/(gated byMARKETDATA_RUN_INTEGRATION_TESTS=true). The PR enforces this policy on the pre-existing tests — see "What changed" below.Summary
/user/startup validation: newHttpTransport.validateToken()(single-attempt, no retry — a 99 s + 1 s + 2 s retry chain on the constructor path is worse UX than failing fast). Wired into theMarketDataClientconstructor.MarketDataLogFormatter(UTC ISO-8601 second resolution,{timestamp} - {logger_name} - {level} - {message}shape).configureLogging(Configuration)readsMARKETDATA_LOGGING_LEVELfrom the cascade and applies it to the SDK's package-level logger. Idempotent; no-op when the env var is unset/blank/invalid.HttpTransport.executeOnceshort-circuits withRateLimitErrorif the latest snapshot reportsremaining <= 0. No-op for cold clients (snapshot starts null). The check fires before any permit is acquired and before any HTTP request is built.What changed
New files
src/main/java/com/marketdata/sdk/MarketDataLogFormatter.java— package-privatejava.util.logging.Formatter. UTC second-resolution timestamp;(anonymous)placeholder whenLogRecord.getLoggerName()returns null.src/test/java/com/marketdata/sdk/MarketDataLogFormatterTest.java— formatter shape,MessageFormatplaceholders, null logger name handling.src/test/java/com/marketdata/sdk/MarketDataClientLoggingTest.java—configureLoggingmechanics: env var application, case-insensitive level parsing, idempotency, no-op paths (unset / blank / invalid). Snapshots and restores the global logger state per test.src/test/java/com/marketdata/sdk/MarketDataClientStartupValidationTest.java— end-to-end of/user/validation against an in-processHttpServer: 200 path, 401 fail-fast, connection-refused fail-fast,validateOnStartup=falseskip, demo-mode skip.src/integrationTest/java/com/marketdata/sdk/MarketDataClientIT.java— moved smoke for the no-arg ctor that previously lived in unit tests but now requires the network.Modified files
src/main/java/com/marketdata/sdk/HttpTransport.java— addsvalidateToken()and the pre-flight check inexecuteOnce. Both are <30 LOC inserts.src/main/java/com/marketdata/sdk/MarketDataClient.java—configureLogging(static, package-private, called from the constructor before the firstLOG.log); validation-on-startup call (single line at the end of the constructor); Javadoc on both constructors now spells out the side effects ofvalidateOnStartup=true.src/test/java/com/marketdata/sdk/HttpTransportRetryTest.java— two new pre-flight tests (preflightFailsImmediatelyWhenRemainingIsZero,preflightAllowsRequestWhenRemainingPositive).src/test/java/com/marketdata/sdk/MarketDataClientTest.java— three pre-existing tests fixed:buildsWithExplicitTokenanduserAgentMatchesSpecnow passvalidateOnStartup=false;demoModeWhenNoTokenAvailablerewritten asdemoModeWhenAllSourcesYieldNullusing the 4-arg ctor +assumeTrue;noArgConstructorAppliesProductionDefaultsremoved (moved to IT — see new files).CLAUDE.md— §5, §7, §8 moved from "Deliberately deferred" to "Already wired in" with implementation details. Latent-gaps section unchanged..gitignore— excludes.claude/(personal Claude Code settings/commands).