Querying Starry Unit Info: An Incremental Sync Walkthrough from Jushuitan to Kingdee YXC
What this strategy solves
In a Jushuitan ↔ Kingdee YXC (Starry) supply-chain integration, measure units (piece, box, kg, etc.) are the shared foundation for items, prices, inventory and purchase documents. On a real project we saw this: when a retail customer first went live, the target system's unit master was empty, and every downstream strategy — items, customers, inventory — refused to run. The single job of the "Query Starry Unit Info" strategy is to pull the existing unit master from the target system back into the integration middleware, using an incremental time window, so that downstream strategies ("Item Sync", "Customer Sync") can do their code-and-name mapping cleanly.
It does not write back to the target system. It only aligns the two sides first — the very first step in the master-data sync chain.
Data flow and field mapping
Flow: source (Kingdee YXC V2) → integration middleware (Qeasy / datahub) → target (a no-op write endpoint on the Qeasy side, used purely as a unit cache for downstream strategies).
The source API is WebAPI GET, hitting Kingdee YXC V2's measure-unit query endpoint, with paging and a time-window increment. Key fields:
| Field | Meaning | Type | Value / Notes |
|---|---|---|---|
| search | Fuzzy search | string | Optional, filter by name/code |
| pagesize | Page size | string | Fixed 100 |
| page | Current page | string | Starts at 1, paged by Qeasy |
| modify_start_time | Modified time – start | string | {{LAST_SYNC_TIME}}000 |
| modify_end_time | Modified time – end | string | {{CURRENT_TIME}}000 |
| enable | Active flag | string | Only active units if set |
| number | Code | string | Unique business key |
| id | System id | string | Platform primary key |
In the middleware layer, Qeasy does two things: caches number and id as a lightweight mapping table, and exposes them to the downstream "Item Sync" strategy so that Jushuitan's unit values can be translated into YXC's number.
How to configure on Qeasy
On the Qeasy integration platform we create a dedicated task for this strategy: source = Kingdee YXC V2, target = the built-in "Write No-Op" placeholder. Key configuration points:
- Source endpoint: API
/jdy/v2/bd/measure_unit, method GET, effect QUERY. EnableautoFillResponseso the platform parses the response shape automatically. - Request params:
pagesizepinned to 100;pagemanaged by Qeasy's paginator; the time window uses the built-in variables{{LAST_SYNC_TIME}}and{{CURRENT_TIME}}to form a closed interval. - Target endpoint: API "Write No-Op", method POST. This is a common "middleware cache" pattern — no write-back to the source, no direct landing on the target; instead the data is staged in Qeasy and queried by strategies that depend on it.
- Primary keys:
numberas business key,idas system key.idCheckis off so an emptyidin the response won't fail the whole batch. - Response mapping: in Qeasy's field-mapping panel, map
number,name,idetc. one-to-one to the intermediate table, keeping the names aligned with the target system's dictionary so dependent strategies can reference them directly.
Implementation steps
We split go-live into three stages, following the common practice of centralizing code mapping in one place:
Stage 1 — Full pull as baseline. First run, set modify_start_time to a very early time (e.g. 1970-01-01) and modify_end_time to now. Pull everything once to seed the unit mapping table. Usually triggered manually; afterwards we cross-check unit counts on both sides.
Stage 2 — Switch to incremental on schedule. After the full run, switch to the normal schedule: */10 7-21 * * *, i.e. every 10 minutes between 07:00 and 21:00. Cover the business hours, miss no changes, and avoid the dawn batch settlement window. LAST_SYNC_TIME is maintained by Qeasy automatically and persisted after each successful run.
Stage 3 — Monitor and reconcile. In Qeasy's run history, watch three signals: "any data returned?", "did paging complete?", "HTTP status code". Under healthy conditions each 10-minute window returns 0–N unit changes; pagesize=100 is usually enough on one page. If you repeatedly see a full page, be alert — the source may be doing a bulk update.
Lessons from the trenches
-
Open-interval time window → missing boundary data. A typical mistake is sending only
modify_start_timeand notmodify_end_time, so you only ever get a snapshot. The safe approach is to send both ends, in millisecond strings (append000), matching the Kingdee YXC V2 API contract. -
Using
searchtogether with the time window can drop data. Oncesearchhas a value, some implementations ignore the time filter. Our rule: in incremental mode never setsearch; rely on the time window. Usesearchonly for ad-hoc historical investigations. -
Ignoring the paging boundary silently eats the last page. With pagesize=100, if the source returns exactly 100, Qeasy's paginator will keep paging until it sees fewer than 100. Easy to miss. Turn on the "page until empty" behavior in Qeasy to avoid silent misses.
-
Pushing disabled units into the middleware. Don't forget the
enableparameter. If the source disables a unit and the downstream strategy still writes items against the old mapping, you'll get "unit does not exist". We add a filter in the Qeasy transformer: disabled units never enter the intermediate table. -
Schedule too dense → source rate-limit. We originally ran
*/5and got HTTP 429 from the source around 10:00. After moving to*/10within 07:00–21:00 it became stable. Incremental sync is not the faster the better — leave headroom for the source.
Where it fits — and where it doesn't
Fit: unit master rarely changes; downstream strategies need a code-mapping baseline; source exposes a modify_time-style incremental API.
Not a fit: units are maintained on both sides (bidirectional); source does not expose modified-time fields; unit count is huge (millions) and really belongs in a dedicated MDM platform.