Skip to content

Commit 50afb8f

Browse files
authored
Merge pull request #12 from YunaBraska/release
feature/spring boot meta data, added NatsServerConfig, logging comman… Former-commit-id: 0f1ca46
2 parents e6c7140 + 0d4a0b3 commit 50afb8f

16 files changed

Lines changed: 994 additions & 139 deletions

README.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,19 @@ public class SomeTest {
2121
[...]
2222
}
2323
```
24+
* See [NatsServerConfig](https://github.com/YunaBraska/nats-streaming-server-embedded/blob/master/src/main/java/berlin/yuna/natsserver/config/NatsServerConfig.java) class for available properties
25+
* @EnableNatsServer is also reading spring config
26+
* @EnableNatsServer parameters are overwriting the spring properties
27+
```yaml
28+
nats:
29+
server:
30+
hb_fail_count: 3
31+
```
2432
33+
```properties
34+
nats.server.hb_fail_count=3
35+
```
2536
### TODO
26-
* calculate on adding parameter
27-
* Spring boot autoconfig for live usage
28-
* Parameter class with description
29-
* Read command errors for exceptions
3037
* Port issues on CI - Seems that the test context is restarting much faster than the ports are shutting down - at least some times
3138

3239
![nats-streaming-server-embedded](src/test/resources/banner.png "nats-streaming-server-embedded")

pom.xml

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
<groupId>berlin.yuna</groupId>
1414
<artifactId>nats-streaming-server-embedded</artifactId>
15-
<version>0.1.0</version>
15+
<version>0.2.0</version>
1616
<packaging>jar</packaging>
1717

1818
<name>${project.artifactId}</name>
@@ -36,11 +36,6 @@
3636
<properties>
3737
<spring-boot.version>2.0.2.RELEASE</spring-boot.version>
3838
<git-project.url>https://github.com/YunaBraska/nats-streaming-server-embedded</git-project.url>
39-
40-
<!-- sonar:sonar -Dsonar.organization=yunabraska-github -Dsonar.host.url=https://sonarcloud.io -Dsonar.login=18ed5d4bd536befbac669d408bb4fd3b2c23f748 -->
41-
<!--<sonar.host.url>https://sonarcloud.io</sonar.host.url>-->
42-
<!--<sonar.organization>yunabraska-github</sonar.organization>-->
43-
<!--<sonar.login>18ed5d4bd536befbac669d408bb4fd3b2c23f748</sonar.login>-->
4439
</properties>
4540

4641
<dependencies>
@@ -56,9 +51,10 @@
5651
<scope>test</scope>
5752
</dependency>
5853
<dependency>
59-
<groupId>org.springframework.boot</groupId>
60-
<artifactId>spring-boot-starter-aop</artifactId>
61-
<version>${spring-boot.version}</version>
54+
<groupId>com.google.code.gson</groupId>
55+
<artifactId>gson</artifactId>
56+
<version>2.8.5</version>
57+
<scope>test</scope>
6258
</dependency>
6359
</dependencies>
6460

src/main/java/berlin/yuna/natsserver/annotation/EnableNatsServer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949

5050
/**
5151
* Passes the original parameters to {@link NatsServer#setNatsServerConfig(String...)} for startup
52+
* {@link berlin.yuna.natsserver.config.NatsServerConfig}
5253
*/
5354
String[] natsServerConfig() default {};
5455

src/main/java/berlin/yuna/natsserver/annotation/EnableNatsServerContextCustomizer.java

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
package berlin.yuna.natsserver.annotation;
22

3+
import berlin.yuna.natsserver.config.NatsServerConfig;
34
import berlin.yuna.natsserver.logic.NatsServer;
45
import org.slf4j.Logger;
56
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
67
import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
78
import org.springframework.context.ConfigurableApplicationContext;
9+
import org.springframework.core.env.ConfigurableEnvironment;
810
import org.springframework.test.context.ContextCustomizer;
911
import org.springframework.test.context.MergedContextConfiguration;
1012
import org.springframework.util.Assert;
1113

14+
import java.util.HashMap;
15+
import java.util.Map;
16+
1217
import static org.slf4j.LoggerFactory.getLogger;
18+
import static org.springframework.util.StringUtils.isEmpty;
1319

1420
public class EnableNatsServerContextCustomizer implements ContextCustomizer {
1521

@@ -37,21 +43,35 @@ public void customizeContext(ConfigurableApplicationContext context, MergedConte
3743
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
3844
Assert.isInstanceOf(DefaultSingletonBeanRegistry.class, beanFactory);
3945

40-
NatsServer natsServerBean = new NatsServer(this.enableNatsServer.natsServerConfig());
41-
try {
42-
natsServerBean.getPort();
43-
} catch (Exception e) {
44-
natsServerBean.getNatsServerConfig().put("port", String.valueOf(enableNatsServer.port()));
46+
if (enableNatsServer == null) {
47+
LOG.debug("Skipping [{}] cause its not defined", EnableNatsServer.class.getSimpleName());
48+
return;
4549
}
4650

51+
NatsServer natsServerBean = new NatsServer(enableNatsServer.natsServerConfig());
52+
natsServerBean.setNatsServerConfig(mergeConfig(context.getEnvironment(), natsServerBean.getNatsServerConfig()));
53+
4754
try {
4855
natsServerBean.start();
4956
} catch (Exception e) {
50-
LOG.error("Failed to initialise [{}]", EnableNatsServer.class, e);
57+
throw new IllegalArgumentException("Failed to initialise " + EnableNatsServer.class.getSimpleName(), e);
58+
// LOG.error("Failed to initialise [{}]", EnableNatsServer.class.getSimpleName(), e);
5159
}
5260

5361
beanFactory.initializeBean(natsServerBean, NatsServer.BEAN_NAME);
5462
beanFactory.registerSingleton(NatsServer.BEAN_NAME, natsServerBean);
5563
((DefaultSingletonBeanRegistry) beanFactory).registerDisposableBean(NatsServer.BEAN_NAME, natsServerBean);
5664
}
65+
66+
private Map<NatsServerConfig, String> mergeConfig(final ConfigurableEnvironment environment, final Map<NatsServerConfig, String> originalConfig) {
67+
Map<NatsServerConfig, String> mergedConfig = new HashMap<>(originalConfig);
68+
for (NatsServerConfig natsServerConfig : NatsServerConfig.values()) {
69+
String key = "nats.server." + natsServerConfig.name().toLowerCase();
70+
String value = environment.getProperty(key);
71+
if (!isEmpty(value) && !mergedConfig.containsKey(natsServerConfig)) {
72+
mergedConfig.put(natsServerConfig, value);
73+
}
74+
}
75+
return mergedConfig;
76+
}
5777
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package berlin.yuna.natsserver.config;
2+
3+
import java.util.UUID;
4+
5+
public enum NatsServerConfig {
6+
7+
//Streaming Server Options
8+
CLUSTER_ID("test-cluster", "[STRING] Cluster ID (default: test-cluster)"),
9+
STORE("MEMORY", "[STRING] Store type: MEMORY|FILE (default: MEMORY)"),
10+
DIR(null, "[STRING] For FILE store type, this is the root directory"),
11+
MAX_CHANNELS("0", "[INT] Max number of channels (0 for unlimited)"),
12+
MAX_SUBS("0", "[INT] Max number of subscriptions per channel (0 for unlimited)"),
13+
MAX_MSGS("0", "[INT] Max number of messages per channel (0 for unlimited)"),
14+
MAX_BYTES("0", "[SIZE] Max messages total size per channel (0 for unlimited)"),
15+
MAX_AGE("0s", "[DURATION] Max duration a message can be stored (\"0s\" for unlimited)"),
16+
MAX_INACTIVITY("0", "[DURATION] Max inactivity (no new message, no subscription) after which a channel can be garbage collected (0 for unlimited)"),
17+
NATS_SERVER(null, "[STRING] Connect to this external NATS Server URL (embedded otherwise)"),
18+
STAN_CONFIG(null, "[STRING] Streaming server configuration file"),
19+
HB_INTERVAL(null, "[DURATION] Interval at which server sends heartbeat to a client"),
20+
HB_TIMEOUT(null, "[DURATION] How long server waits for a heartbeat response"),
21+
HB_FAIL_COUNT(null, "[INT] Number of failed heartbeats before server closes the client connection"),
22+
FT_GROUP(null, "[STRING] Name of the FT Group. A group can be 2 or more servers with a single active server and all sharing the same datastore."),
23+
24+
//Streaming Server Clustering Options
25+
CLUSTERED("false", "[BOOL] Run the server in a clustered configuration (default: false)"),
26+
CLUSTER_NODE_ID(UUID.randomUUID().toString(), "[STRING] ID of the node within the cluster if there is no stored ID (default: random UUID)"),
27+
CLUSTER_BOOTSTRAP("false", "[BOOL] Bootstrap the cluster if there is no existing state by electing self as leader (default: false)"),
28+
CLUSTER_PEERS(null, "[STRING] List of cluster peer node IDs to bootstrap cluster state."),
29+
CLUSTER_LOG_PATH(null, "[STRING] Directory to store log replication data"),
30+
CLUSTER_LOG_CACHE_SIZE("512", "[INT] Number of log entries to cache in memory to reduce disk IO (default: 512)"),
31+
CLUSTER_LOG_SNAPSHOTS("2", "[INT] Number of log snapshots to retain (default: 2)"),
32+
CLUSTER_TRAILING_LOGS(null, "[INT] Number of log entries to leave after a snapshot and compaction"),
33+
CLUSTER_SYNC(null, "[BOOL] Do a file sync after every write to the replication log and message store"),
34+
CLUSTER_RAFT_LOGGING(null, "[BOOL] Enable logging from the Raft library (disabled by default)"),
35+
36+
//Streaming Server File Store Options
37+
FILE_COMPACT_ENABLED(null, "[BOOL] Enable file compaction"),
38+
FILE_COMPACT_FRAG(null, "[INT] File fragmentation threshold for compaction"),
39+
FILE_COMPACT_INTERVAL(null, "[INT] Minimum interval (in seconds) between file compactions"),
40+
FILE_COMPACT_MIN_SIZE(null, "[SIZE] Minimum file size for compaction"),
41+
FILE_BUFFER_SIZE(null, "[SIZE] File buffer size (in bytes)"),
42+
FILE_CRC(null, "[BOOL] Enable file CRC-32 checksum"),
43+
FILE_CRC_POLY(null, "[INT] Polynomial used to make the table used for CRC-32 checksum"),
44+
FILE_SYNC(null, "[BOOL] Enable File.Sync on Flush"),
45+
FILE_SLICE_MAX_MSGS(null, "[INT] Maximum number of messages per file slice (subject to channel limits)"),
46+
FILE_SLICE_MAX_BYTES(null, "[SIZE] Maximum file slice size - including index file (subject to channel limits)"),
47+
FILE_SLICE_MAX_AGE(null, "[DURATION] Maximum file slice duration starting when the first message is stored (subject to channel limits)"),
48+
FILE_SLICE_ARCHIVE_SCRIPT(null, "[STRING] Path to script to use if you want to archive a file slice being removed"),
49+
FILE_FDS_LIMIT(null, "[INT] Store will try to use no more file descriptors than this given limit"),
50+
FILE_PARALLEL_RECOVERY(null, "[INT] On startup, number of channels that can be recovered in parallel"),
51+
52+
//Streaming Server SQL Store Options
53+
SQL_DRIVER(null, "[STRING] Name of the SQL Driver (\"mysql\" or \"postgres\")"),
54+
SQL_DATA_SOURCE(null, "[STRING] Datasource used when opening an SQL connection to the database"),
55+
SQL_NO_CACHING(null, "[BOOL] Enable/Disable caching for improved performance"),
56+
SQL_MAX_OPEN_CONNS(null, "[INT] Maximum number of opened connections to the database"),
57+
58+
//Streaming Server TLS Options
59+
SECURE(null, "-[BOOL] Use a TLS connection to the NATS server without verification; weaker than specifying certificates."),
60+
TLS_CLIENT_KEY(null, "-[STRING] Client key for the streaming server"),
61+
TLS_CLIENT_CERT(null, "-[STRING] Client certificate for the streaming server"),
62+
TLS_CLIENT_CACERT(null, "-[STRING] Client certificate CA for the streaming server"),
63+
64+
//Streaming Server Logging Options
65+
STAN_DEBUG("false", "[BOOL] Enable STAN debugging output"),
66+
STAN_TRACE("false", "[BOOL] Trace the raw STAN protocol"),
67+
68+
//NATS Server Options
69+
ADDR("0.0.0.0", "[STRING] Bind to host address (default: 0.0.0.0)"),
70+
PORT("4222", "[INT] Use port for clients (default: 4222)"),
71+
PID(null, "[STRING] File to store PID"),
72+
HTTP_PORT(null, "[INT] Use port for http monitoring"),
73+
HTTPS_PORT(null, "[INT] Use port for https monitoring"),
74+
CONFIG(null, "[STRING] Configuration file"),
75+
76+
//NATS Server Logging Options
77+
LOG(null, "[STRING] File to redirect log output"),
78+
LOGTIME("true", "[BOOL] Timestamp log entries (default: true)"),
79+
SYSLOG(null, "[STRING] Enable syslog as log method"),
80+
REMOTE_SYSLOG(null, "[STRING] Syslog server addr (udp://localhost:514)"),
81+
DEBUG("false", "[BOOL] Enable debugging output"),
82+
TRACE("false", "[BOOL] Trace the raw protocol"),
83+
84+
//NATS Server Authorization Options
85+
USER(null, "[STRING] User required for connections"),
86+
PASS(null, "[STRING] Password required for connections"),
87+
AUTH(null, "[STRING] Authorization token required for connections"),
88+
89+
//TLS Options
90+
TLS("false", "[BOOL] Enable TLS, do not verify clients (default: false)"),
91+
TLSCERT(null, "[STRING] Server certificate file"),
92+
TLSVERIFY(null, "[BOOL] Enable TLS, verify client certificates"),
93+
TLSCACERT(null, "[STRING] Client certificate CA for verification"),
94+
95+
//NATS Clustering Options
96+
ROUTES(null, "[STRING] Routes to solicit and connect"),
97+
CLUSTER(null, "[STRING] Cluster URL for solicited routes");
98+
99+
private final String defaultValue;
100+
private final String description;
101+
102+
NatsServerConfig(String defaultValue, String description) {
103+
this.defaultValue = defaultValue;
104+
this.description = description;
105+
}
106+
107+
public String getDefaultValue() {
108+
return defaultValue;
109+
}
110+
111+
public String getDescription() {
112+
return description;
113+
}
114+
115+
/**
116+
* Command line property key
117+
*
118+
* @return key for command line
119+
*/
120+
public String getKey() {
121+
String key = name().toLowerCase();
122+
key = getDescription().startsWith("-") ? "-" + key : "--" + key;
123+
key = getDescription().startsWith("[BOOL]") ? key + "=" : key + " ";
124+
return key;
125+
}
126+
}

0 commit comments

Comments
 (0)