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

io.vertx.tp.plugin.shared.SharedClientImpl Maven / Gradle / Ivy

There is a newer version: 0.9.0
Show newest version
package io.vertx.tp.plugin.shared;

import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.shareddata.AsyncMap;
import io.vertx.core.shareddata.LocalMap;
import io.vertx.core.shareddata.SharedData;
import io.vertx.up.atom.Kv;
import io.vertx.up.exception.WebException;
import io.vertx.up.exception.web._500SharedDataModeException;
import io.vertx.up.fn.Fn;
import io.vertx.up.log.Annal;

import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@SuppressWarnings("all")
public class SharedClientImpl implements SharedClient {

    private static final Annal LOGGER = Annal.get(SharedClientImpl.class);

    private static final ConcurrentMap CLIENTS =
        new ConcurrentHashMap<>();

    private final transient Vertx vertx;
    private transient LocalMap syncMap;
    private transient AsyncMap asyncMap;
    private transient String poolName;

    SharedClientImpl(final Vertx vertx, final String name) {
        this.vertx = vertx;
        this.poolName = name;
    }

    public static  SharedClient create(final Vertx vertx, final String name) {
        return Fn.pool(CLIENTS, name, () -> new SharedClientImpl(vertx, name));
    }

    private void async(final Handler>> handler) {
        if (Objects.isNull(this.asyncMap)) {
            final SharedData sd = this.vertx.sharedData();
            // Async map created
            LOGGER.info(Info.INFO_ASYNC_START);
            sd.getAsyncMap(this.poolName, res -> {
                if (res.succeeded()) {
                    this.asyncMap = res.result();
                    LOGGER.info(Info.INFO_ASYNC_END, String.valueOf(this.asyncMap.hashCode()), this.poolName);
                    handler.handle(Future.succeededFuture(res.result()));
                } else {
                    final WebException error = new _500SharedDataModeException(getClass(), res.cause());
                    handler.handle(Future.failedFuture(error));
                }
            });
        } else {
            handler.handle(Future.succeededFuture(this.asyncMap));
        }
    }

    private LocalMap sync() {
        if (Objects.isNull(this.syncMap)) {
            final SharedData sd = this.vertx.sharedData();
            // Sync map created
            this.syncMap = sd.getLocalMap(this.poolName);
            LOGGER.info(Info.INFO_SYNC, String.valueOf(this.syncMap.hashCode()), this.poolName);
        }
        return this.syncMap;
    }

    @Override
    public SharedClient switchClient(final String name) {
        return SharedClientImpl.create(this.vertx, name);
    }

    @Override
    public Kv put(final K key, final V value) {
        final V reference = this.sync().get(key);
        // Add & Replace
        Fn.safeSemi(null == reference, LOGGER,
            () -> this.sync().put(key, value),
            () -> this.sync().replace(key, value));
        return Kv.create(key, value);
    }

    @Override
    public Kv put(final K key, final V value, final int seconds) {
        Kv result = this.put(key, value);
        LOGGER.info(Info.INFO_TIMER_PUT, String.valueOf(key), String.valueOf(seconds));
        this.vertx.setTimer(seconds * 1000, id -> {
            final V existing = this.get(key);
            if (Objects.nonNull(existing)) {
                LOGGER.info(Info.INFO_TIMER_EXPIRE, String.valueOf(key));
                this.remove(key);
            } else {
                LOGGER.info(Info.INFO_TIMER_REMOVED, String.valueOf(key));
            }
        });
        return result;
    }

    @Override
    public SharedClient put(final K key, final V value,
                                  final Handler>> handler) {
        this.async(map -> map.result().get(key, res -> {
            if (res.succeeded()) {
                final V reference = res.result();
                Fn.safeSemi(null == reference, LOGGER,
                    () -> map.result().put(key, value, added -> {
                        if (added.succeeded()) {
                            handler.handle(Future.succeededFuture(Kv.create(key, value)));
                        } else {
                            final WebException error = new _500SharedDataModeException(getClass(), added.cause());
                            handler.handle(Future.failedFuture(error));
                        }
                    }),
                    () -> map.result().replace(key, value, replaced -> {
                        if (replaced.succeeded()) {
                            handler.handle(Future.succeededFuture(Kv.create(key, value)));
                        } else {
                            final WebException error = new _500SharedDataModeException(getClass(), replaced.cause());
                            handler.handle(Future.failedFuture(error));
                        }
                    }));
            } else {
                final WebException error = new _500SharedDataModeException(getClass(), res.cause());
                handler.handle(Future.failedFuture(error));
            }
        }));
        return this;
    }

    @Override
    public SharedClient put(final K key, final V value, final int seconds,
                                  final Handler>> handler) {
        final SharedClient reference = this.put(key, value, handler);
        LOGGER.info(Info.INFO_TIMER_PUT, String.valueOf(key), String.valueOf(seconds));
        this.vertx.setTimer(seconds * 1000, id -> this.remove(key, res -> LOGGER.info(Info.INFO_TIMER_EXPIRE, key)));
        return reference;
    }

    @Override
    public Kv remove(final K key) {
        final V removed = this.sync().remove(key);
        return Kv.create(key, removed);
    }

    @Override
    public V get(final K key) {
        return this.sync().get(key);
    }

    @Override
    public boolean clear() {
        this.sync().clear();
        return true;
    }

    @Override
    public V get(final K key, final boolean once) {
        final V value = this.get(key);
        if (once) {
            this.remove(key);
        }
        return value;
    }

    @Override
    public SharedClient remove(final K key,
                                     final Handler>> handler) {
        this.async(map -> map.result().remove(key, res -> {
            if (res.succeeded()) {
                final V reference = res.result();
                handler.handle(Future.succeededFuture(Kv.create(key, reference)));
            } else {
                final WebException error = new _500SharedDataModeException(getClass(), res.cause());
                handler.handle(Future.failedFuture(error));
            }
        }));
        return this;
    }

    @Override
    public SharedClient get(final K key,
                                  final Handler> handler) {
        this.async(map -> map.result().get(key, handler));
        return this;
    }

    @Override
    public SharedClient get(K key, boolean once,
                                  Handler> handler) {
        final SharedClient reference = this.get(key, handler);
        if (once) {
            this.async(map -> map.result().remove(key, handler));
        }
        return reference;
    }

    @Override
    public SharedClient clear(Handler> handler) {
        this.async(map -> map.result().clear(result -> handler.handle(Future.succeededFuture(Boolean.TRUE))));
        return this;
    }

    /*
     * Shared Enhancement for
     *
     * 1) Session Management
     * 2) Cache Management
     * 3) Login/Logout Management
     */
    @Override
    public SharedClient size(Handler> handler) {
        this.async(map -> map.result().size(handler));
        return this;
    }

    @Override
    public SharedClient keys(Handler>> handler) {
        this.async(map -> map.result().keys(handler));
        return this;
    }

    @Override
    public int size() {
        return this.sync().size();
    }

    @Override
    public Set keys() {
        return this.sync().keySet();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy