Consume SpiceDB LookupResources gRPC stream from Clojure using Java gRPC library

34 Views Asked by At

The SpiceDB gRPC endpoint for LookupResources returns a gRPC stream of resource IDs with a cursor.

Consuming gRPC streams from Clojure can be gnarly. I know I need to reify StreamObserver and consume the stream until no items remain.

I could not find a good self-contained example of how to do this using the io.grpc Java gRPC libraries without introducing core.async. How would you consume a gRPC response stream and return a Clojure vector of all exhausted results?

At this point, we can assume the result set is small and can be eagerly consumed without any additional async structures. Bonus points for lazy loading, but lazy loading would probably require some state management.

1

There are 1 best solutions below

1
On

When using a blocking stub, use iterator-seq on the blocking stream response, collect the items in an atom, and deref the atom:

(let [!results (atom [])
        request  (-> (PermissionService$LookupResourcesRequest/newBuilder)
                   (.setSubject (make-subject subject-type subject-id))
                   (.setPermission permission)
                   (with-consistency consistency)
                   (.setResourceObjectType resource-type)
                   (.build))
        ^PermissionService$LookupResourcesResponse response
                 (.lookupResources service request)]
    (doseq [x (iterator-seq response) ;; note iterator-seq.
            :let [resource-id (.getResourceObjectId x)]]
      (swap! !results conj [resource-type resource-id]))
    @!results)

For a non-blocking gRPC service stub, the implementation will have to change.