oscerd commented on code in PR #27195:
URL: https://github.com/apache/camel/pull/27195#discussion_r4155850223


##########
components/camel-openfga/src/main/docs/openfga-component.adoc:
##########
@@ -320,12 +320,68 @@ No check is registered for an injected `openFgaClient`, 
which can point anywhere
 about. Set `healthCheckProducerEnabled=false` on the component, or 
`healthCheckEnabled=false` on the policy, to
 turn them off.
 
+=== Reading the graph
+
+`readTuples` answers "what access exists", as opposed to `check`'s "may this 
subject do this". Here `user`, `relation`
+and `object` are a *filter* rather than a subject, and the body comes back as 
a list of maps keyed `user`, `relation`,
+`object` and `timestamp` — deliberately the keys `writeTuples` and 
`deleteTuples` accept, so a route can revoke what
+it just read without reshaping anything:
+
+[source,java]
+------------------------------------------------------------
+from("direct:revokeEverythingBobHas")
+        
.to("openfga:readTuples?storeId={{fga.store}}&object=document:&user=user:bob")
+        .to("openfga:deleteTuples?storeId={{fga.store}}");
+------------------------------------------------------------
+
+[NOTE]
+.What OpenFGA accepts as a read filter
+====
+The filter is narrower than "every part is optional". Measured against OpenFGA 
1.21.0:
+
+* no filter at all — reads the whole store, a page at a time;
+* `object=document:` *plus* a `user` — reads that user's tuples of that object 
type;
+* `object=document:budget` — reads that object's tuples, with or without a 
user or relation;
+* `user` alone, `relation` alone, or `object=document:` alone — **rejected**, 
because OpenFGA requires an object type
+  as soon as any filter is given and will not accept an empty object id and an 
empty user together.
+
+The component checks this before the call and names the option to change, 
rather than letting an opaque HTTP 400
+through. Note this is also why a type-only `document:` is accepted here but 
not as an `object` anywhere else: a read
+filter and an identifier have different rules.
+====
+
+`readChanges` reads the change log, which is the building block for keeping a 
cache or a projection in step with the
+graph. Each entry adds an `operation` of `WRITE` or `DELETE`.
+
+Both are paged. `pageSize` bounds one request, and the token the page returns 
arrives on
+`CamelOpenFgaContinuationToken`; feed it back through `continuationToken` for 
the next page:
+
+[source,java]
+------------------------------------------------------------
+from("timer:sync?period=30000")
+        .to("openfga:readChanges?storeId={{fga.store}}&type=document"
+            + "&continuationToken=${exchangeProperty.fgaToken}")

Review Comment:
   Right on both counts — the example was broken, and it was broken in the way 
that matters least visibly: it would have *run*, polled happily, and silently 
re-read the same first page every 30 seconds.
   
   Fixed in `808b3526ee7a` using your suggestion, and I verified the syntax 
rather than guessing at it: `${variable.global:...}` is exercised by 
`SimpleTest` (`assertExpression("${variable.global:cheese}", "gorgonzola")`), 
and `setVariable(String, Expression)` exists on `ProcessorDefinition`, so the 
route now reads
   
   ```java
   from("timer:sync?period=30000")
           .to("openfga:readChanges?storeId={{fga.store}}&type=document"
               + "&continuationToken=${variable.global:fgaToken}")
           .setVariable("global:fgaToken", 
header("CamelOpenFgaContinuationToken"))
           .split(body()).to("direct:applyChange");
   ```
   
   Rather than assert that this works, there is now an integration test that 
drives exactly that route twice against a real OpenFGA container and asserts 
the second poll returns a *different* change from the first — which is 
precisely what fails if the token does not survive the exchange boundary. That 
test would have failed on the `exchangeProperty` version.
   
   Your restart point is in the docs too: a global variable lives in the 
`CamelContext`, so a poller that must resume across a restart should keep the 
token wherever the deployment already persists state.
   
   _Claude Code on behalf of oscerd_



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to