All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.datarouter.gcp.spanner.op.read.SpannerBaseReadOp Maven / Gradle / Ivy

There is a newer version: 0.0.126
Show newest version
/*
 * Copyright © 2009 HotPads ([email protected])
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.datarouter.gcp.spanner.op.read;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;

import com.google.cloud.spanner.DatabaseClient;
import com.google.cloud.spanner.Key;
import com.google.cloud.spanner.Key.Builder;
import com.google.cloud.spanner.KeyRange;
import com.google.cloud.spanner.KeyRange.Endpoint;
import com.google.cloud.spanner.KeySet;
import com.google.cloud.spanner.Options;
import com.google.cloud.spanner.ResultSet;

import io.datarouter.gcp.spanner.field.SpannerBaseFieldCodec;
import io.datarouter.gcp.spanner.field.SpannerFieldCodecRegistry;
import io.datarouter.gcp.spanner.op.SpannerBaseOp;
import io.datarouter.instrumentation.trace.TraceSpanGroupType;
import io.datarouter.instrumentation.trace.TracerTool;
import io.datarouter.model.field.Field;
import io.datarouter.model.key.primary.PrimaryKey;
import io.datarouter.opencensus.adapter.DatarouterOpencensusTool;
import io.datarouter.storage.config.Config;
import io.datarouter.util.tuple.Range;
import io.opencensus.common.Scope;

public abstract class SpannerBaseReadOp extends SpannerBaseOp>{

	protected final DatabaseClient client;
	protected final Config config;
	protected final SpannerFieldCodecRegistry codecRegistry;
	protected final String tableName;

	public SpannerBaseReadOp(
			DatabaseClient client,
			Config config,
			SpannerFieldCodecRegistry codecRegistry,
			String tableName){
		//TODO implement traces
		super("Spanner read");
		this.client = client;
		this.config = config;
		this.codecRegistry = codecRegistry;
		this.tableName = tableName;
	}

	public abstract KeySet buildKeySet();

	protected > Key primaryKeyConversion(K key){
		if(key == null){
			return Key.of();
		}
		Builder mutationKey = Key.newBuilder();
		for(SpannerBaseFieldCodec codec : codecRegistry.createCodecs(key.getFields())){
			if(codec.getField().getValue() == null){
				break;
			}
			mutationKey = codec.setKey(mutationKey);
		}
		return mutationKey.build();
	}

	protected  List callClient(List columnNames, List> fields, Supplier object){
		String spanName = getClass().getSimpleName();
		Optional opencensusSpan = Optional.empty();
		try(var $ = TracerTool.startSpan(spanName, TraceSpanGroupType.DATABASE)){
			opencensusSpan = DatarouterOpencensusTool.createOpencensusSpan();
			List results = callClientInternal(columnNames, fields, object);
			TracerTool.appendToSpanInfo("got " + results.size());
			return results;
		}finally{
			opencensusSpan.ifPresent(Scope::close);
		}
	}

	private  List callClientInternal(List columnNames, List> fields, Supplier object){
		Integer offset = config.findOffset().orElse(0);
		ResultSet rs;
		if(config.getLimit() != null){
			int limit = offset + config.getLimit();
			rs = client.singleUseReadOnlyTransaction().read(
					tableName,
					buildKeySet(),
					columnNames,
					Options.limit(limit));
		}else{
			rs = client.singleUseReadOnlyTransaction().read(tableName, buildKeySet(), columnNames);
		}
		List result = createFromResultSet(rs, object, fields);
		if(offset >= result.size()){
			return List.of();
		}
		if(offset > 0){
			return result.subList(offset, result.size());
		}
		return result;
	}

	protected > KeyRange convertRange(Range range){
		KeyRange.Builder builder = KeyRange.newBuilder()
				.setStart(primaryKeyConversion(range.getStart()))
				.setEnd(primaryKeyConversion(range.getEnd()));
		if(range.isEmptyStart()){
			builder.setStartType(Endpoint.CLOSED);
		}else{
			builder.setStartType(range.getStartInclusive() ? Endpoint.CLOSED : Endpoint.OPEN);
		}
		if(range.isEmptyEnd()){
			builder.setEndType(Endpoint.CLOSED);
		}else{
			builder.setEndType(range.getEndInclusive() ? Endpoint.CLOSED : Endpoint.OPEN);
		}
		return builder.build();
	}

	protected  List createFromResultSet(ResultSet set, Supplier objectSupplier, List> fields){
		List> codecs = codecRegistry.createCodecs(fields);
		List objects = new ArrayList<>();
		while(set.next()){
			F object = objectSupplier.get();
			codecs.forEach(codec -> codec.setField(object, set));
			objects.add(object);
		}
		return objects;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy