Skip to content

[WiP] Huawei API integration#204

Draft
yatharthranjan wants to merge 11 commits into
masterfrom
claude/huawei-api-integration-hxdqtl
Draft

[WiP] Huawei API integration#204
yatharthranjan wants to merge 11 commits into
masterfrom
claude/huawei-api-integration-hxdqtl

Conversation

@yatharthranjan

Copy link
Copy Markdown
Member

Initial implementation of Huawei HealthKit, powered by claude

claude added 9 commits July 14, 2026 10:25
…erns

Captures the two connector generations (generic kafka-connect-rest-source
framework used by Fitbit vs. the newer oura-library + thin Connect glue
split used by Oura), the runtime polling/auth/conversion flow, config and
Docker/CI setup, and a checklist for adding a new vendor integration such
as Huawei following the Oura pattern.
Registers the two new Gradle modules, pins radar-schemas-commons
0.9.0-SNAPSHOT (huawei_schemas branch not yet released) as a separate
version-catalog entry so existing modules keep the stable release, and
adds the user/UserRepository domain types mirroring oura-library's
pattern.
Adds the domain logic for the Huawei Health Kit connector, mirroring
oura-library's split of pure-Kotlin logic from Kafka Connect glue:

- request/: RestRequest, RequestGenerator, HuaweiRequestGenerator (offset
  tracking, per-route backoff on 401/403/429/etc), HuaweiResult/HuaweiError.
- route/: HuaweiRoute base (OAuth2-authorized GET/POST + time-range
  chunking), three concrete route kinds covering the Health Kit Data API's
  endpoints - HuaweiSampleSetRoute (POST sampleSet:polymerize, raw or
  groupByTime-aggregated), HuaweiHealthRecordRoute (GET healthRecords),
  HuaweiActivityRecordRoute (GET activityRecords) - and HuaweiRouteFactory,
  a single registry mapping all ~54 Huawei data types from the
  radar-huawei-connector schema spec to their endpoint, dataTypeName, and
  Avro record builder.
- converter/: FieldValues (typed accessor for Huawei's field-value sample
  point format) and generic converters that turn API responses into
  TopicData for the registered Avro records.

Field-value key names are best-effort (Huawei HiHealth Field naming
convention); this was verified to compile against a locally-published
radar-schemas-commons 0.9.0-SNAPSHOT (huawei_schemas branch) since none of
the real snapshot hosts are reachable from this sandbox - flagged in
comments for verification against a live API response.
Mirrors kafka-connect-oura-source: HuaweiSourceConnector (periodic user
refresh + task reconfiguration), HuaweiSourceTask (round-robin polling
across routes, JSON->Avro->SourceRecord conversion via AvroData),
KafkaOffsetManager, and HuaweiServiceUserRepository (Ktor-based
rest-source-authorizer client with OAuth2 client-credentials auth and
cached user/token lookups).

HuaweiRestSourceConnectorConfig is written in Kotlin and loop-generates
its ~110 per-data-type `huawei.<key>.enabled`/`huawei.<key>.topic`
ConfigDef entries from huawei-library's HuaweiRouteFactory.definitions
registry, rather than hand-duplicating a static field per topic as
Fitbit/Oura do - the same registry also drives which routes
HuaweiSourceTask actually builds, so the connector config and the set of
polled routes can never drift out of sync.

Could not compile this module in this sandbox: packages.confluent.io
(needed for kafka-connect-api/kafka-connect-avro-converter) is blocked by
the sandbox's egress policy - confirmed this is pre-existing and applies
equally to kafka-connect-oura-source, not something introduced here.
huawei-library (the part of this change with real logic to verify) does
compile cleanly against a locally-published radar-schemas-commons
0.9.0-SNAPSHOT.
Adds docker/source-huawei.properties.template, a radar-huawei-connector
docker-compose service, a README section, and registers the
kafka-connect-huawei-source image in both CI workflow matrices. Updates
ARCHITECTURE.md to document the Huawei module and the route-registry
config-generation pattern it introduces for connectors with a large
number of data types.
huawei-library tests (verified passing in this sandbox against a locally
published radar-schemas-commons 0.9.0-SNAPSHOT):
- FieldValuesTest: typed-value array and flattened-object parsing.
- HuaweiRouteFactoryTest: builds every one of the ~54 registered route
  definitions, feeds each a fixture payload shaped for its endpoint kind,
  and asserts the converter produces exactly one record on the expected
  topic without throwing - this caught two real bugs during development
  (a bad endTime field on HuaweiCgmBloodGlucose, and a private extension
  function shadowing HuaweiDataConverter's).

kafka-connect-huawei-source gets a config test mirroring the existing
*RestSourceConnectorConfigTest convention, plus checks that
enabledTopics() reflects the shared HuaweiRouteFactory.definitions
registry and honors per-type huawei.<key>.enabled overrides. Could not
run this one in-sandbox (see prior commit: packages.confluent.io is
blocked here for every kafka-connect-*-source module, pre-existing and
unrelated to this change).

Also switches huawei-library's JUnit integration from kotlin-test-junit
(JUnit4) to kotlin-test-junit5, since oura-library's copy-pasted
dependency block conflicts with the JUnit Platform the radar-kotlin
Gradle plugin configures the test task with - previously unnoticed only
because no *-library module had tests yet.
`./gradlew check` runs ktlint over every module; auto-formatted the
mechanical issues (semicolons, wrapping) and manually split a handful of
lines ktlint couldn't auto-correct. huawei-library:check is now fully
green (ktlint + all 5 tests) in this sandbox.
ktlint is static analysis and doesn't need dependency resolution to run,
so this module's Kotlin sources could be linted even though they can't
be compiled in this sandbox. Wraps long ConfigDef.define() calls and
doc-string constants, and simplifies the getUserRepository()/
initialize() flow slightly in the process.
Adds yatharthranjan@onsentia.com alongside the existing KCL address in
the Huawei Docker image label and CI workflow author fields.
@yatharthranjan
yatharthranjan marked this pull request as draft July 14, 2026 13:16
@yatharthranjan yatharthranjan changed the title [WiP] Claude/huawei api integration hxdqtl [WiP] Huawei API integration Jul 14, 2026
claude added 2 commits July 14, 2026 13:45
- Wrap the okhttp3.HttpUrl from getHuaweiUserRepositoryUrl() in
  URLBuilder(...).build() before passing it as createClient's Ktor
  Url parameter, matching how the token URL was already handled
  (and how OuraServiceUserRepository does it).
- Throwable.message is nullable; fall back to a default string before
  passing it to UserNotAuthorizedException's non-null constructor.

These only surfaced in real CI since packages.confluent.io is blocked in
this sandbox, so kafka-connect-huawei-source couldn't be compiled here -
verified via ktlint (which needs no dependency resolution) that the fix
introduces no new style issues.
ktlintKotlinScriptCheck also lints .gradle.kts files; wraps the two
GitHub Packages credential lines that exceeded 100 chars.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants