Skip to content

Commit

Permalink
Readme refactor (#97)
Browse files Browse the repository at this point in the history
* update readme for major version update
  • Loading branch information
kortemik authored Mar 11, 2024
1 parent 3bcb2a7 commit 27905b6
Show file tree
Hide file tree
Showing 6 changed files with 708 additions and 18 deletions.
218 changes: 203 additions & 15 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ AGPLv3 with link:https://github.com/teragrep/rlp_03/blob/master/LICENSE#L665-L67
== Features
Current

- RELP Server
- Fast (~100 000 transactions in a second per thread)
- Secure (TLS)

== Setting dependencies
== Usage
=== Setting dependencies
[source, xml]
----
<?xml version="1.0" encoding="UTF-8"?>
Expand All @@ -22,40 +24,226 @@ Current
<dependency>
<groupId>com.teragrep</groupId>
<artifactId>rlp_03</artifactId>
<version>1.0.0</version>
<version>${see_latest_at_github}</version>
</dependency>
</dependencies>
</project>
----

== Example
NOTE: See https://github.com/teragrep/rlp_01[rlp_01] for relp client

NOTE: See https://github.com/teragrep/rlo_06[rlo_06] for syslog decoding

=== Examples

Dependencies for examples

[source, xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<dependencies>
<!-- this library -->
<dependency>
<groupId>com.teragrep</groupId>
<artifactId>rlp_03</artifactId>
<version>${see_latest_at_github}</version>
</dependency>
<!-- rlp_01 for relp-client -->
<dependency>
<groupId>com.teragrep</groupId>
<artifactId>rlp_01</artifactId>
<version>${see_latest_at_github}</version>
</dependency>
</dependencies>
</project>
----

Server with shared handler for all connections

[source, java]
----
package com.teragrep.rlp_03.readme;
import com.teragrep.rlp_01.RelpBatch;
import com.teragrep.rlp_01.RelpConnection;
import com.teragrep.rlp_03.FrameContext;
import com.teragrep.rlp_03.Server;
import com.teragrep.rlp_03.SyslogFrameProcessor;
import com.teragrep.rlp_03.ServerFactory;
import com.teragrep.rlp_03.config.Config;
import com.teragrep.rlp_03.delegate.*;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
final Consumer<byte[]> cbFunction;
/**
* For use cases in the README.adoc
*/
public class ReadmeTest {
@Test
public void testServerSetup() {
int listenPort = 10601;
int threads = 1; // processing threads shared across the connections
Config config = new Config(listenPort, threads);
cbFunction = (message) -> {
System.out.println(new String(message));
/*
* System.out.println is used to print the frame payload
*/
Consumer<FrameContext> syslogConsumer = new Consumer<FrameContext>() {
// NOTE: synchronized because frameDelegateSupplier returns this instance for all the parallel connections
@Override
public synchronized void accept(FrameContext frameContext) {
System.out.println(frameContext.relpFrame().payload().toString());
}
};
int port = 1601;
Server server = new Server(port, new SyslogFrameProcessor(cbFunction));
server.start();
while (true) {
Thread.sleep(1000L);
/*
* DefaultFrameDelegate accepts Consumer<FrameContext> for processing syslog frames
*/
DefaultFrameDelegate frameDelegate = new DefaultFrameDelegate(syslogConsumer);
/*
* Same instance of the frameDelegate is shared with every connection
*/
Supplier<FrameDelegate> frameDelegateSupplier = new Supplier<FrameDelegate>() {
@Override
public FrameDelegate get() {
System.out.println("Providing frameDelegate for a connection");
return frameDelegate;
}
};
/*
* ServerFactory is used to create server instances
*/
ServerFactory serverFactory = new ServerFactory(config, frameDelegateSupplier);
Server server;
try {
server = serverFactory.create();
}
catch (IOException ioException) {
throw new UncheckedIOException(ioException);
}
/*
* One may use server.run(); or create the server into a new thread
*/
Thread serverThread = new Thread(server);
/*
* Run the server
*/
serverThread.start();
/*
* Wait for startup, server is available for connections once it finished setup
*/
try {
server.startup.waitForCompletion();
System.out.println("server started at port <" + listenPort + ">");
}
catch (InterruptedException interruptedException) {
throw new RuntimeException(interruptedException);
}
/*
* Send Hello, World! via rlp_01
*/
new ExampleRelpClient(listenPort).send("Hello, World!");
/*
* Stop server
*/
server.stop();
/*
* Wait for stop to complete
*/
try {
serverThread.join();
}
catch (InterruptedException interruptedException) {
throw new RuntimeException(interruptedException);
}
System.out.println("server stopped at port <" + listenPort + ">");
/*
* Close the frameDelegate
*/
try {
frameDelegate.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* ExampleRelpClient using rlp_01 for demonstration
*/
private class ExampleRelpClient {
private final int port;
ExampleRelpClient(int port) {
this.port = port;
}
public void send(String record) {
RelpConnection relpConnection = new RelpConnection();
try {
relpConnection.connect("localhost", port);
}
catch (IOException | TimeoutException exception) {
throw new RuntimeException(exception);
}
RelpBatch relpBatch = new RelpBatch();
relpBatch.insert(record.getBytes(StandardCharsets.UTF_8));
while (!relpBatch.verifyTransactionAll()) {
relpBatch.retryAllFailed();
try {
relpConnection.commit(relpBatch);
}
catch (IOException | TimeoutException exception) {
throw new RuntimeException(exception);
}
}
try {
relpConnection.disconnect();
}
catch (IOException | TimeoutException exception) {
throw new RuntimeException(exception);
}
finally {
relpConnection.tearDown();
}
}
}
}
----

If a separate handler is required for each connection which doesn’t need to be a thread-safe, create a new FrameDelegate in the Supplier<FrameDelegate>

[source, java]
----
Supplier<FrameDelegate> frameDelegateSupplier = () -> {
System.out.println("Providing frameDelegate for a connection");
return new DefaultFrameDelegate(frameContext -> System.out.println(frameContext.relpFrame().payload().toString()));
};
----

If a deferred handler is required for command processing, pass custom RelpEvent implementation to DefaultFrameDelegate via the Map<String, RelpEvent> constructor. See ReadmeDeferredTest.java for an example.

== Contributing

// Change the repository name in the issues link to match with your project's name
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/teragrep/rlp_03/delegate/RelpEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
import java.nio.charset.StandardCharsets;
import java.util.function.Consumer;

abstract class RelpEvent implements Consumer<FrameContext>, AutoCloseable {
public abstract class RelpEvent implements Consumer<FrameContext>, AutoCloseable {
protected RelpFrameTX createResponse(
RelpFrame rxFrame,
String command,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
import java.util.ArrayList;
import java.util.List;

class RelpEventClose extends RelpEvent {
public class RelpEventClose extends RelpEvent {

private static final Logger LOGGER = LoggerFactory.getLogger(RelpEventClose.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
import java.util.ArrayList;
import java.util.List;

class RelpEventOpen extends RelpEvent {
public class RelpEventOpen extends RelpEvent {

private static final String responseData = "200 OK\nrelp_version=0\n"
+ "relp_software=RLP-01,1.0.1,https://teragrep.com\n"
Expand Down
Loading

0 comments on commit 27905b6

Please sign in to comment.