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

io.datakernel.crdt.CrdtServer Maven / Gradle / Ivy

There is a newer version: 3.1.0
Show newest version
/*
 * Copyright (C) 2015-2019 SoftIndex LLC.
 *
 * 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.datakernel.crdt;

import io.datakernel.common.exception.StacklessException;
import io.datakernel.csp.net.MessagingWithBinaryStreaming;
import io.datakernel.datastream.StreamConsumer;
import io.datakernel.datastream.csp.ChannelDeserializer;
import io.datakernel.datastream.csp.ChannelSerializer;
import io.datakernel.eventloop.Eventloop;
import io.datakernel.net.AbstractServer;
import io.datakernel.net.AsyncTcpSocket;
import io.datakernel.promise.Promise;
import io.datakernel.serializer.BinarySerializer;

import java.net.InetAddress;

import static io.datakernel.crdt.CrdtMessaging.*;
import static io.datakernel.csp.binary.ByteBufSerializer.ofJsonCodec;

public final class CrdtServer, S> extends AbstractServer> {
	private final CrdtStorage client;
	private final CrdtDataSerializer serializer;
	private final BinarySerializer keySerializer;

	private CrdtServer(Eventloop eventloop, CrdtStorage client, CrdtDataSerializer serializer) {
		super(eventloop);
		this.client = client;
		this.serializer = serializer;

		keySerializer = serializer.getKeySerializer();
	}

	public static , S> CrdtServer create(Eventloop eventloop, CrdtStorage client, CrdtDataSerializer serializer) {
		return new CrdtServer<>(eventloop, client, serializer);
	}

	public static , S> CrdtServer create(Eventloop eventloop, CrdtStorage client, BinarySerializer keySerializer, BinarySerializer stateSerializer) {
		return new CrdtServer<>(eventloop, client, new CrdtDataSerializer<>(keySerializer, stateSerializer));
	}

	@Override
	protected void serve(AsyncTcpSocket socket, InetAddress remoteAddress) {
		MessagingWithBinaryStreaming messaging =
				MessagingWithBinaryStreaming.create(socket, ofJsonCodec(MESSAGE_CODEC, RESPONSE_CODEC));
		messaging.receive()
				.then(msg -> {
					if (msg == null) {
						return Promise.ofException(new StacklessException(CrdtServer.class, "Unexpected end of stream"));
					}
					if (msg == CrdtMessages.UPLOAD) {
						return messaging.receiveBinaryStream()
								.transformWith(ChannelDeserializer.create(serializer))
								.streamTo(StreamConsumer.ofPromise(client.upload()))
								.then($ -> messaging.send(CrdtResponses.UPLOAD_FINISHED))
								.then($ -> messaging.sendEndOfStream())
								.whenResult($ -> messaging.close());

					}
					if (msg == CrdtMessages.REMOVE) {
						return messaging.receiveBinaryStream()
								.transformWith(ChannelDeserializer.create(keySerializer))
								.streamTo(StreamConsumer.ofPromise(client.remove()))
								.then($ -> messaging.send(CrdtResponses.REMOVE_FINISHED))
								.then($ -> messaging.sendEndOfStream())
								.whenResult($ -> messaging.close());
					}
					if (msg instanceof Download) {
						return client.download(((Download) msg).getToken())
								.whenResult($ -> messaging.send(new DownloadStarted()))
								.then(supplier -> supplier
										.transformWith(ChannelSerializer.create(serializer))
										.streamTo(messaging.sendBinaryStream()));
					}
					return Promise.ofException(new StacklessException(CrdtServer.class, "Message type was added, but no handling code for it"));
				})
				.whenComplete(($, e) -> {
					if (e == null) {
						return;
					}
					logger.warn("got an error while handling message (" + e + ") : " + this);
					String prefix = e.getClass() != StacklessException.class ? e.getClass().getSimpleName() + ": " : "";
					messaging.send(new ServerError(prefix + e.getMessage()))
							.then($1 -> messaging.sendEndOfStream())
							.whenResult($1 -> messaging.close());
				});
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy