use of io.atomix.primitive.session.SessionClient in project atomix by atomix.
the class RaftFuzzTest method runFuzzTest.
/**
* Runs a single fuzz test.
*/
private void runFuzzTest() throws Exception {
reset();
createServers(randomNumber(5) + 3);
final Object lock = new Object();
final AtomicLong index = new AtomicLong();
final Map<Integer, Long> indexes = new HashMap<>();
ThreadContext context = new SingleThreadContext("fuzz-test");
int clients = randomNumber(10) + 1;
for (int i = 0; i < clients; i++) {
ReadConsistency consistency = randomConsistency();
RaftClient client = createClient();
SessionClient proxy = createProxy(client, consistency);
Scheduler scheduler = new SingleThreadContext("fuzz-test-" + i);
final int clientId = i;
scheduler.schedule(Duration.ofMillis((100 * clients) + (randomNumber(50) - 25)), Duration.ofMillis((100 * clients) + (randomNumber(50) - 25)), () -> {
long lastLinearizableIndex = index.get();
int type = randomNumber(4);
switch(type) {
case 0:
proxy.execute(operation(PUT, CLIENT_SERIALIZER.encode(Maps.immutableEntry(randomKey(), randomString(1024 * 16))))).<Long>thenApply(CLIENT_SERIALIZER::decode).thenAccept(result -> {
synchronized (lock) {
if (result < lastLinearizableIndex) {
System.out.println(result + " is less than last linearizable index " + lastLinearizableIndex);
System.exit(1);
} else if (result > index.get()) {
index.set(result);
}
Long lastSequentialIndex = indexes.get(clientId);
if (lastSequentialIndex == null) {
indexes.put(clientId, result);
} else if (result < lastSequentialIndex) {
System.out.println(result + " is less than last sequential index " + lastSequentialIndex);
System.exit(1);
} else {
indexes.put(clientId, lastSequentialIndex);
}
}
});
break;
case 1:
proxy.execute(operation(GET, CLIENT_SERIALIZER.encode(randomKey())));
break;
case 2:
proxy.execute(operation(REMOVE, CLIENT_SERIALIZER.encode(randomKey()))).<Long>thenApply(CLIENT_SERIALIZER::decode).thenAccept(result -> {
synchronized (lock) {
if (result < lastLinearizableIndex) {
System.out.println(result + " is less than last linearizable index " + lastLinearizableIndex);
System.exit(1);
} else if (result > index.get()) {
index.set(result);
}
Long lastSequentialIndex = indexes.get(clientId);
if (lastSequentialIndex == null) {
indexes.put(clientId, result);
} else if (result < lastSequentialIndex) {
System.out.println(result + " is less than last sequential index " + lastSequentialIndex);
System.exit(1);
} else {
indexes.put(clientId, lastSequentialIndex);
}
}
});
break;
case 3:
proxy.execute(operation(INDEX)).<Long>thenApply(CLIENT_SERIALIZER::decode).thenAccept(result -> {
synchronized (lock) {
switch(consistency) {
case LINEARIZABLE:
case LINEARIZABLE_LEASE:
if (result < lastLinearizableIndex) {
System.out.println(result + " is less than last linearizable index " + lastLinearizableIndex);
System.exit(1);
} else if (result > index.get()) {
index.set(result);
}
case SEQUENTIAL:
Long lastSequentialIndex = indexes.get(clientId);
if (lastSequentialIndex == null) {
indexes.put(clientId, result);
} else if (result < lastSequentialIndex) {
System.out.println(result + " is less than last sequential index " + lastSequentialIndex);
System.exit(1);
} else {
indexes.put(clientId, lastSequentialIndex);
}
}
}
});
}
});
}
scheduleRestarts(context);
Thread.sleep(Duration.ofMinutes(15).toMillis());
}
use of io.atomix.primitive.session.SessionClient in project atomix by atomix.
the class PrimaryBackupTest method testEvents.
/**
* Tests submitting sequential events to all sessions.
*/
private void testEvents(int nodes, int backups, Replication replication) throws Throwable {
createServers(nodes);
PrimaryBackupClient client1 = createClient();
SessionClient session1 = createProxy(client1, backups, replication);
session1.addEventListener(CHANGE_EVENT, event -> {
threadAssertNotNull(event);
resume();
});
PrimaryBackupClient client2 = createClient();
SessionClient session2 = createProxy(client2, backups, replication);
session2.addEventListener(CHANGE_EVENT, event -> {
threadAssertNotNull(event);
resume();
});
session1.execute(operation(READ, null)).thenRun(this::resume);
session2.execute(operation(READ, null)).thenRun(this::resume);
await(5000, 2);
session1.execute(operation(EVENT, SERIALIZER.encode(false))).thenRun(this::resume);
await(5000, 3);
}
use of io.atomix.primitive.session.SessionClient in project atomix by atomix.
the class DefaultRaftClient method sessionBuilder.
@Override
public RaftSessionClient.Builder sessionBuilder(String primitiveName, PrimitiveType primitiveType, ServiceConfig serviceConfig) {
return new RaftSessionClient.Builder() {
@Override
public SessionClient build() {
// Create a proxy builder that uses the session manager to open a session.
Supplier<CompletableFuture<SessionClient>> proxyFactory = () -> CompletableFuture.completedFuture(new DefaultRaftSessionClient(primitiveName, primitiveType, serviceConfig, partitionId, DefaultRaftClient.this.protocol, selectorManager, sessionManager, readConsistency, communicationStrategy, threadContextFactory.createContext(), minTimeout, maxTimeout));
SessionClient proxy;
ThreadContext context = threadContextFactory.createContext();
// If the recovery strategy is set to RECOVER, wrap the builder in a recovering proxy client.
if (recoveryStrategy == Recovery.RECOVER) {
proxy = new RecoveringSessionClient(clientId, partitionId, primitiveName, primitiveType, proxyFactory, context);
} else {
proxy = proxyFactory.get().join();
}
// If max retries is set, wrap the client in a retrying proxy client.
if (maxRetries > 0) {
proxy = new RetryingSessionClient(proxy, context, maxRetries, retryDelay);
}
return new BlockingAwareSessionClient(proxy, context);
}
};
}
use of io.atomix.primitive.session.SessionClient in project atomix by atomix.
the class PrimaryBackupTest method testSequentialEvent.
/**
* Tests submitting a sequential event.
*/
private void testSequentialEvent(int nodes, int backups, Replication replication) throws Throwable {
createServers(nodes);
AtomicLong count = new AtomicLong();
AtomicLong index = new AtomicLong();
PrimaryBackupClient client = createClient();
SessionClient session = createProxy(client, backups, replication);
session.<Long>addEventListener(CHANGE_EVENT, event -> {
threadAssertEquals(count.incrementAndGet(), 2L);
threadAssertEquals(index.get(), SERIALIZER.decode(event.value()));
resume();
});
session.execute(operation(EVENT, SERIALIZER.encode(true))).<Long>thenApply(SERIALIZER::decode).thenAccept(result -> {
threadAssertNotNull(result);
threadAssertEquals(count.incrementAndGet(), 1L);
index.set(result);
resume();
});
await(5000, 2);
}
use of io.atomix.primitive.session.SessionClient in project atomix by atomix.
the class PrimaryBackupTest method testManyEventsAfterPrimaryShutdown.
/**
* Tests events after a primary shutdown.
*/
private void testManyEventsAfterPrimaryShutdown(Replication replication) throws Throwable {
List<PrimaryBackupServer> servers = createServers(5);
PrimaryBackupClient client = createClient();
SessionClient session = createProxy(client, 3, replication);
session.addEventListener(CHANGE_EVENT, event -> {
threadAssertNotNull(event);
resume();
});
for (int i = 0; i < 10; i++) {
session.execute(operation(EVENT, SERIALIZER.encode(true))).thenRun(this::resume);
await(5000, 2);
}
PrimaryBackupServer leader = servers.stream().filter(s -> s.getRole() == Role.PRIMARY).findFirst().get();
leader.stop().get(10, TimeUnit.SECONDS);
for (int i = 0; i < 10; i++) {
session.execute(operation(EVENT, SERIALIZER.encode(true))).thenRun(this::resume);
await(5000, 2);
}
}
Aggregations