Server: make binary transfer utilities available in Context

When a feature implementation receives a large binary or has to send it, it needs to get a reference to the binary transfer database of the SiLAServer. I propose to inject this object into all calls via the io.grpc.Context, so a feature implementation could just use BinaryDatabase.current() to get the reference.

This could be achieved by a ServerInterceptor:

import io.grpc.Context;
import io.grpc.Contexts;
import io.grpc.Metadata;
import io.grpc.ServerCall;
import io.grpc.ServerCallHandler;
import io.grpc.ServerInterceptor;
import sila_java.library.server_base.binary_transfer.database.BinaryDatabase;

public class BinaryDatabaseInjector implements ServerInterceptor {
    public static final Context.Key<BinaryDatabase> BINARY_DATABASE_KEY = Context.key("BINARY_DATABASE_KEY");
    private final BinaryDatabase binaryDatabase;

    public BinaryDatabaseInjector(BinaryDatabase binaryDatabase) {
        this.binaryDatabase = binaryDatabase;
    }

    @Override
    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
            final ServerCall<ReqT, RespT> call, final Metadata headers, final ServerCallHandler<ReqT, RespT> next) {
        return Contexts.interceptCall(Context.current().withValue(BINARY_DATABASE_KEY, this.binaryDatabase), call, headers, next);
    }
}

This alone would allow BinaryDatabase db = BinaryDatabaseInjector.BINARY_DATABASE_KEY.get(Context.current()), which in my opinion would already be a huge improvement. By converting BinaryDatabase from an interface to an abstract class with the following method, this could even be shortened to BinaryDatabase db = BinaryDatabase.current(). This is also how the ServerMetadataContainer works.

public static BinaryDatabase current() {
    return BinaryDatabaseInjector.BINARY_DATABASE_KEY.get(Context.current());
}
Edited Aug 12, 2022 by Niklas Mertsch
Assignee Loading
Time tracking Loading