Transaction

What I want to do

I want to confirm whether the join() method called by concurrent DgraphClient transactions is executed synchronously or concurrently?

  public Response doRequest(Request request) {
    return ExceptionUtil.withExceptionUnwrapped(() -> asyncTransaction.doRequest(request).join());
  }

Dgraph metadata

dgraph version
Dgraph version   : v20.11.2
Dgraph codename  : tchalla-2
Commit timestamp : 2021-02-23 13:07:17 +0530
Branch           : HEAD
Go version       : go1.15.5
jemalloc enabled : true

Is this the java client? @abhimanyusinghgaur could you help?

Yes it is.

join() is synchronous within a thread.

If you have one thread, that has sequential join() calls, then each call to join() would block the thread, so that they will occur one after the other, i.e., synchronously.

If you have multiple threads, each one calling one join(), then all the join() calls should be concurrent because the threads are concurrent.

And as you say, you have concurrent transactions, that means the calls to doRequest() are concurrent => join() is concurrent.

Well, thank you for your reply. Another problem is that I found that the ForkJoinPool thread pool is used by default to execute the requested task, but under high concurrency, the execution of each task becomes the LIFO mode, which will cause the first request to be processed longer and the transaction will start. The one with the larger timestamp will be executed first. Does this have any effect? Why use this thread pool?

  public DgraphAsyncClient(DgraphGrpc.DgraphStub... stubs) {
    this.stubs = asList(stubs);
    this.executor = ForkJoinPool.commonPool();
    this.jwtLock = new ReentrantReadWriteLock();
  }

By default, ForkJoinPool is used as the executor. If you want, you can supply a different executor using this constructor:

public DgraphAsyncClient(Executor executor, DgraphGrpc.DgraphStub... stubs) {
    this.stubs = asList(stubs);
    this.executor = executor;
    this.jwtLock = new ReentrantReadWriteLock();
  }

Refer this thread for more details: Dgraph4j support for custom executor

Define a DgraphStub through the serviceName of K8s, is it concurrent or serial to establish connection and communication for multiple threads in the thread pool? Is there a recommended client configuration for high concurrency scenarios?Now the default client is like this.

    public static void initDgraphClient(boolean withAuthHeader) {
        ManagedChannel grouo1FirstChannel = ManagedChannelBuilder
                .forAddress(alphaHostName, firstAlphaPort).usePlaintext()
                .build();
        DgraphStub grouo1FirstStub = DgraphGrpc.newStub(grouo1FirstChannel);

        ClientInterceptor timeoutInterceptor = new ClientInterceptor(){
            @Override
            public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
                    MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
                return next.newCall(method, callOptions.withDeadlineAfter(500, TimeUnit.MILLISECONDS));
            }
        };
        grouo1FirstStub.withInterceptors(timeoutInterceptor);
        dgraphClient = new DgraphClient(grouo1FirstStub);
    }

There is one more question. I would like to trouble you to answer it again. If a request contains query, set mutation, and delete mutation at the same time, if forkjoinpool is used, will these operations be processed in parallel by multiple threads? Such as between set mutation and deletion mutation.