Skip to content

Commit 747099b

Browse files
example added
1 parent 71bc598 commit 747099b

30 files changed

Lines changed: 4098 additions & 26 deletions

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ Thumbs.db
2525
.env
2626
.env.local
2727

28+
# Python (examples/mock-server)
29+
.venv/
30+
__pycache__/
31+
*.pyc
32+
2833
# Logs / coverage
2934
*.log
3035
hs_err_pid*

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ The Java SDK must also satisfy the canonical, cross-language [SDK Requirements](
6363
**Already wired in:**
6464
- §1.1 client object — `MarketDataClient` with two public constructors: a no-arg one for production (everything from the cascade) and a 4-arg `(apiKey, baseUrl, apiVersion, validateOnStartup)` for tests and short-lived runtimes. All fields `final` (immutable). Default base URL `https://api.marketdata.app`, default API version `v1`, single shared `HttpClient`, `User-Agent: marketdata-sdk-java/{version}` (version auto-detected from JAR manifest), `close()` for resource release, `getRateLimits()` accessor.
6565
- §4 configuration cascade — `Configuration.resolve(...)` does explicit → `MARKETDATA_*` env var → `.env` in CWD → default. Env var names live in `EnvVars` (package-private, in the SDK root package). `baseUrl` and `apiVersion` are normalized (trailing/leading slashes stripped) and validated (scheme http/https, host present, no query/fragment/user-info on `baseUrl`; `[A-Za-z0-9._-]+` on `apiVersion`) at resolution time, so misconfigured cascade inputs fail at construction with a clear message instead of producing malformed URLs later.
66-
- §5 demo mode + `validateOnStartup` parameter on the 4-arg constructor (defaults to `true` via the no-arg constructor); token redaction via `Tokens.redact` (matches the spec example `***…***YKT0`). `runStartupValidation` fires a single `GET /v1/user/` via `utilities.user(RetryPolicy.noRetry())`, skipping in demo mode; the no-retry policy keeps construction snappy on a slow/down API.
66+
- §5 demo mode + `validateOnStartup` parameter on the 4-arg constructor (defaults to `true` via the no-arg constructor); token redaction via `Tokens.redact` (matches the spec example `***…***YKT0`). `runStartupValidation` fires a single `GET /user/` (unversioned, like `/status/` and `/headers/`) via `utilities.validateAuth()` with `RetryPolicy.noRetry()`, skipping in demo mode; the no-retry policy keeps construction snappy on a slow/down API.
6767
- §6 sealed `MarketDataException` hierarchy with the 7 canonical subtypes and full support context (`requestId`, `requestUrl`, `statusCode`, `timestamp`, `exceptionType`) + `getSupportInfo()`.
6868
- §7 logging — `MarketDataLogging.configure(...)` installs `CanonicalLogFormatter` (the spec's `{timestamp} - {logger_name} - {level} - {message}` shape) on `com.marketdata.sdk` and applies the level from `MARKETDATA_LOGGING_LEVEL`. Detects consumer-pre-configured loggers (handler attached or level set) and backs off entirely so embedding the SDK doesn't clobber existing logging setups.
6969
- §8 rate-limit tracking — `RateLimitHeaders.parse` reads the four `x-api-ratelimit-*` headers per response (all-or-nothing: a partial header set returns null rather than emitting a snapshot with phantom zeros); `HttpTransport.latestRateLimits` keeps the latest snapshot, exposed via `client.getRateLimits()`. §10.3 preflight (`HttpTransport.checkRateLimitPreflight`) fails fast on `remaining=0`, but only while `now < reset` — once the reset window elapses the request goes through so the next response refreshes the snapshot.

Makefile

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Convenience wrapper around ./gradlew and the consumer-test / mock-server.
2+
# Run `make` (no args) or `make help` for the target list.
3+
4+
CONSUMER_DIR := examples/consumer-test
5+
MOCK_DIR := examples/mock-server
6+
7+
.DEFAULT_GOAL := help
8+
9+
# ---------------------------------------------------------------------------
10+
# Help
11+
# ---------------------------------------------------------------------------
12+
13+
.PHONY: help
14+
help: ## Show this help
15+
@awk 'BEGIN {FS = ":.*##"; printf "Usage:\n make \033[36m<target>\033[0m\n\nTargets:\n"} \
16+
/^# ===/ { in_section = 1; next } \
17+
/^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-22s\033[0m %s\n", $$1, $$2 } \
18+
/^## ---/ { printf "\n\033[33m%s\033[0m\n", substr($$0, 5) }' $(MAKEFILE_LIST)
19+
@echo ""
20+
@echo "Typical workflow:"
21+
@echo " make publish # publish SDK to mavenLocal"
22+
@echo " make mock-server # in another terminal"
23+
@echo " make demo-config # in a third terminal"
24+
25+
# ---------------------------------------------------------------------------
26+
## --- SDK build ---
27+
# ---------------------------------------------------------------------------
28+
29+
.PHONY: build
30+
build: ## Full build: unit tests + Spotless + JaCoCo (JDK 17)
31+
./gradlew build
32+
33+
.PHONY: test
34+
test: ## Unit tests only
35+
./gradlew test
36+
37+
.PHONY: spotless
38+
spotless: ## Apply code formatting
39+
./gradlew spotlessApply
40+
41+
.PHONY: clean
42+
clean: ## Clean all Gradle outputs (SDK + consumer-test)
43+
./gradlew clean
44+
cd $(CONSUMER_DIR) && ./gradlew clean
45+
46+
.PHONY: publish
47+
publish: ## Publish SDK to ~/.m2 (prereq for any demo)
48+
./gradlew publishToMavenLocal
49+
50+
# ---------------------------------------------------------------------------
51+
## --- Mock server ---
52+
# ---------------------------------------------------------------------------
53+
54+
.PHONY: mock-server
55+
mock-server: ## Start the FastAPI mock server (blocks, Ctrl+C to stop)
56+
cd $(MOCK_DIR) && ./run.sh
57+
58+
# ---------------------------------------------------------------------------
59+
## --- Consumer demos (need `make publish` first) ---
60+
# ---------------------------------------------------------------------------
61+
62+
.PHONY: demo-quickstart
63+
demo-quickstart: ## Idiomatic per-resource usage tour (live API; grows as resources land)
64+
cd $(CONSUMER_DIR) && ./gradlew runQuickstart
65+
66+
.PHONY: demo-live
67+
demo-live: ## Live API smoke (needs MARKETDATA_TOKEN in examples/consumer-test/.env)
68+
cd $(CONSUMER_DIR) && ./gradlew runLive
69+
70+
.PHONY: demo-config
71+
demo-config: ## Demo mode, cascade, validation (needs mock-server)
72+
cd $(CONSUMER_DIR) && ./gradlew runDemoConfig
73+
74+
.PHONY: demo-exceptions
75+
demo-exceptions: ## Every MarketDataException subtype (needs mock-server)
76+
cd $(CONSUMER_DIR) && ./gradlew runExceptions
77+
78+
.PHONY: demo-retry
79+
demo-retry: ## Retry, Retry-After, preflight (needs mock-server)
80+
cd $(CONSUMER_DIR) && ./gradlew runRetry
81+
82+
.PHONY: demo-response
83+
demo-response: ## Response<T> surface features (needs mock-server)
84+
cd $(CONSUMER_DIR) && ./gradlew runResponse
85+
86+
.PHONY: demo-concurrency
87+
demo-concurrency: ## 50-permit semaphore (needs mock-server)
88+
cd $(CONSUMER_DIR) && ./gradlew runConcurrency
89+
90+
.PHONY: demos-all
91+
demos-all: ## Run every mock-server-based demo back-to-back (needs mock-server)
92+
cd $(CONSUMER_DIR) && ./gradlew runDemoConfig runExceptions runRetry runResponse runConcurrency

0 commit comments

Comments
 (0)