Repository navigation
Replies: 2 comments 2 replies
|
In STA v2 we've added:
The problem with uniqueness is a tricky one. The standard can't say too much about it, since what makes an Entity unique depends very much on the use case. Two Things can both have a Datastream with the same name. Two Things may have the same name, but a different Location. Having multiple Observations in the same Datastream with the same phenomenonTime is quite common in the water domain, where a lab analysis is often repeated with different parameters... When importing data I always have a single thread handling non-Observation entities, and a per-datastream thread handling Observations. Since inserting an Observation requires a lock on the Datastream, there is no performance benefit to having multiple threads inserting Observations for the same Datastream. Instead, I use data arrays or batch-processing to batch-upload Observations. |
|
Practical update from our side. We adopted the per-datastream threading model @hylkevds described, and it removed both the race and the performance puzzle we had been chasing: adding concurrency to observation inserts was not helping because each insert locks the Datastream anyway. One thread per datastream, one latest-observation query at startup, then batch upload. Simpler and faster. On the shared-server namespacing point: we prefix every entity name with GEO_ and bind entities to a Project per site (GEO_TGV, GEO_BDJ). It works for isolation, but it does guarantee that two parties who genuinely model the same phenomenon will never converge on one entity. That trade-off feels like something a national profile should settle, not each implementer independently. One thing we can now confirm from running three targets concurrently: the write-capability discovery step we built (does this server support dataArray batch? client-specified IDs? what does it do on duplicate?) has been essential. Each of the three servers (FROST v1.1, CollaborAll v1.1, Fraunhofer v2.0) behaves differently, and there is currently no way to discover that programmatically. A machine-readable capabilities document, even a minimal one, would remove a lot of trial-and-error. Still very interested in @hylkevds's answers to the three v2 questions above :) |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
A finding from our translation layer that I think applies to anyone writing to STA concurrently, and that produced wrong data with no error of any kind.
The pattern. Server-side ids are server-generated, so a client that has to be restart-safe cannot store them as its key. The advice in #11 applies: resolve entities by querying for them. That means every writer implements the same upsert: GET ?$filter=name eq '', then POST if absent.
The problem. That is check-then-act, and STA does not require entity names to be unique. So when two requests race, both find the entity absent and both create it, and the server is right not to complain. We resolve datastreams in parallel, and entities that are shared between datastreams (one Sensor per sensor model, one ObservedProperty per phenomenon) are exactly the ones that race. We ended up with five copies each of one Sensor and one ObservedProperty.
Why this is worth raising rather than just fixing. No 409, no error, no signal. We only noticed because a later name lookup returned five hits where it expected one, and we happened to have written that lookup to log multiplicity. Implemented the obvious way, taking the first result, this stays invisible forever. Data is silently duplicated and every downstream consumer sees a plausible answer.
We fixed it on our side with a per-key single-flight around the create, so concurrent first-sight resolutions of one name collapse into one lookup and one POST. That works, but it is a client-side fix for something the server could settle definitively.
What would remove the class of bug, roughly in order of preference in our opinion:
Related, and a reason not to solve it with names alone: on a shared server, name-keyed upsert also means our lookup can bind to another participant's entity that happens to share a name, inheriting their definition and units silently. We prefix every entity name we create to avoid it. That works, but it guarantees fragmentation: if two parties genuinely should converge on one Fill level concept, prefixing ensures they never do. Namespacing on shared servers might be worth a convention at programme level.
Has anyone else writing concurrently hit this? @hylkevds, is client-defined id / uniqueness something v2 addresses?
All reactions