ferry icon indicating copy to clipboard operation
ferry copied to clipboard

OfflineMutationTypedLink - How to pass same client to OfflineMutationTypedLink

Open francescreig opened this issue 2 years ago • 12 comments

Hello,

I am been working on creating an OfflineMutationTypedLink same as this PR #147. I've nearly implemented but I have a problem that actually it was pointed here: when you want to reexecute offline mutations, calling requestController.add(req) would not execute the request since it does not see any response. Trying to instead call client.request(req) (see below)

void _handleOnConnect() => mutationQueueBox.values.forEach((json) async {
      final OperationRequest req = serializers.deserialize(json);

      // Run unexecuted mutations
      await client.request(req).firstWhere((res) => res.dataSource == DataSource.Link); <---- here
 });

leads me to call again the request method that I override on the same OfflineMutationTypedLink, so I end up in a recursive call that freezes the app.

Here it is pointed to pass the client as a dependency, but I think I am failing on this, since using the same client (OfflineClient) that internally has this OfflineMutationTypedLink gives a recursive calls.

This is my request method that I override:

@override
Stream<OperationResponse<TData, TVars>> request<TData, TVars>(
  OperationRequest<TData, TVars> request, [
  NextTypedLink<TData, TVars>? forward,
]) {
  return _handleRequest(request, forward).transform(_responseTransformer());
}

Stream<OperationResponse<TData, TVars>> _handleRequest<TData, TVars>(
  OperationRequest<TData, TVars> request, [
  NextTypedLink<TData, TVars>? forward,
]) {
  // Forward along any operations that aren't Mutations
  if (_isMutation(request) == false) return forward!(request);

  if (connectionStatus.hasConnection) {
    connected = true;
  } else {
    connected = false;
  }
  if (connected) return forward!(request);

  // Save mutation to the queue
  mutationQueueBox.add(serializers.serialize(request));

  // Add an optimistic patch to the cache, if necessary
  if (request.optimisticResponse != null) {
    cache.writeQuery(
      request,
      request.optimisticResponse,
      optimisticRequest: config?.persistOptimisticResponse == false ? request : null,
    );
    return forward!(request);
  }

  // Don't forward
  return NeverStream();
}

So when I set the setter connected to true it runs a method to execute the requests, thus entering in a recursive call (calling request overrided method from above):

void _handleOnConnect() async {
  for (final json in mutationQueueBox.values) {
    final req = serializers.deserialize(json);

    // Run unexecuted mutations
    await client
        .request(req)
        .firstWhere((res) => res.dataSource == DataSource.Link && res.operationRequest == req);
  }
}

francescreig avatar Feb 28 '23 19:02 francescreig