
io.reactiverse.pgclient.impl.WizzardoPgPool Maven / Gradle / Ivy
Show all versions of reactive-pg-client Show documentation
/*
* Copyright (C) 2017 Julien Viet
*
* 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.reactiverse.pgclient.impl;
import io.reactiverse.pgclient.PgConnection;
import io.reactiverse.pgclient.PgPool;
import io.reactiverse.pgclient.PgTransaction;
import io.reactiverse.pgclient.shared.AsyncResult;
import io.reactiverse.pgclient.shared.Future;
import io.reactiverse.pgclient.shared.Handler;
/**
* Todo :
*
* - handle timeout when acquiring a connection
* - for per statement pooling, have several physical connection and use the less busy one to avoid head of line blocking effect
*
* @author Julien Viet
* @author Emad Alblueshi
*/
public class WizzardoPgPool extends PgClientBase implements PgPool {
private final WizzardoPgConnectionFactory factory;
private final ConnectionPool pool;
public WizzardoPgPool(WizzardoPgPoolOptions options) {
int maxSize = options.getMaxSize();
if (maxSize < 1) {
throw new IllegalArgumentException("Pool max size must be > 0");
}
this.factory = new WizzardoPgConnectionFactory(options);
this.pool = new ConnectionPool(completionHandler -> factory.connect(completionHandler::handle), maxSize);
}
@Override
public void getConnection(Handler> handler) {
pool.acquire(new ConnectionWaiter(handler));
}
@Override
public void begin(Handler> handler) {
getConnection(ar -> {
if (ar.succeeded()) {
WizzardoPgConnection conn = (WizzardoPgConnection) ar.result();
PgTransaction tx = conn.begin(true);
handler.handle(Future.succeededFuture(tx));
} else {
handler.handle(Future.failedFuture(ar.cause()));
}
});
}
@Override
protected void schedule(CommandBase> cmd) {
pool.acquire(new CommandWaiter() {
@Override
protected void onSuccess(Connection conn) {
conn.schedule(cmd);
conn.close(this);
}
@Override
protected void onFailure(Throwable cause) {
cmd.fail(cause);
}
});
}
private abstract class CommandWaiter implements Connection.Holder, Handler> {
private Connection conn;
protected abstract void onSuccess(Connection conn);
protected abstract void onFailure(Throwable cause);
@Override
public void handleNotification(int processId, String channel, String payload) {
// What should we do ?
}
@Override
public void handle(AsyncResult ar) {
if (ar.succeeded()) {
Connection conn = ar.result();
this.conn = conn;
conn.init(this);
onSuccess(conn);
} else {
onFailure(ar.cause());
}
}
@Override
public void handleClosed() {
}
@Override
public void handleException(Throwable err) {
}
@Override
public Connection connection() {
return conn;
}
}
private class ConnectionWaiter implements Handler> {
private final Handler> handler;
private ConnectionWaiter(Handler> handler) {
this.handler = handler;
}
@Override
public void handle(AsyncResult ar) {
if (ar.succeeded()) {
Connection conn = ar.result();
WizzardoPgConnection holder = new WizzardoPgConnection(conn);
conn.init(holder);
handler.handle(Future.succeededFuture(holder));
} else {
handler.handle(Future.failedFuture(ar.cause()));
}
}
}
@Override
public void close() {
pool.close();
factory.close();
}
}