Skip to content

Commit edcab0c

Browse files
committed
Ref #25533: support SpEL for heartbeat-timeout setting
1 parent 9b54a2e commit edcab0c

7 files changed

Lines changed: 134 additions & 28 deletions

File tree

src/main/java/eu/openanalytics/containerproxy/backend/AbstractContainerBackend.java

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,6 @@
2020
*/
2121
package eu.openanalytics.containerproxy.backend;
2222

23-
import com.fasterxml.jackson.databind.MapperFeature;
24-
import com.fasterxml.jackson.databind.ObjectMapper;
25-
import com.fasterxml.jackson.databind.SerializationFeature;
26-
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
27-
import com.google.common.base.Charsets;
28-
import eu.openanalytics.containerproxy.ContainerProxyApplication;
2923
import eu.openanalytics.containerproxy.ContainerProxyException;
3024
import eu.openanalytics.containerproxy.auth.IAuthenticationBackend;
3125
import eu.openanalytics.containerproxy.backend.strategy.IProxyTargetMappingStrategy;
@@ -55,16 +49,14 @@
5549
import org.springframework.core.env.Environment;
5650

5751
import javax.inject.Inject;
58-
import java.io.File;
5952
import java.io.FileInputStream;
6053
import java.io.IOException;
6154
import java.io.OutputStream;
62-
import java.math.BigInteger;
6355
import java.nio.file.Files;
6456
import java.nio.file.Paths;
65-
import java.security.MessageDigest;
66-
import java.security.NoSuchAlgorithmException;
67-
import java.util.*;
57+
import java.util.HashMap;
58+
import java.util.Map;
59+
import java.util.Properties;
6860
import java.util.function.BiConsumer;
6961
import java.util.regex.Matcher;
7062
import java.util.regex.Pattern;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* ContainerProxy
3+
*
4+
* Copyright (C) 2016-2021 Open Analytics
5+
*
6+
* ===========================================================================
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the Apache License as published by
10+
* The Apache Software Foundation, either version 2 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* Apache License for more details.
17+
*
18+
* You should have received a copy of the Apache License
19+
* along with this program. If not, see <http://www.apache.org/licenses/>
20+
*/
21+
package eu.openanalytics.containerproxy.model.runtime.runtimevalues;
22+
23+
public class HeartbeatTimeoutKey extends RuntimeValueKey<Long> {
24+
25+
private HeartbeatTimeoutKey() {
26+
super("openanalytics.eu/sp-heartbeat-timeout",
27+
"SHINYPROXY_HEARTBEAT_TIMEOUT",
28+
false,
29+
true,
30+
false,
31+
true, Long.class);
32+
}
33+
34+
public static HeartbeatTimeoutKey inst = new HeartbeatTimeoutKey();
35+
36+
}

src/main/java/eu/openanalytics/containerproxy/model/spec/ProxySpec.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public class ProxySpec {
4141

4242
private Long maxLifeTime;
4343
private Boolean stopOnLogout;
44-
private Long heartbeatTimeout;
44+
private String heartbeatTimeout;
4545

4646
public String getId() {
4747
return id;
@@ -148,11 +148,11 @@ public void setStopOnLogout(Boolean stopOnLogout) {
148148
this.stopOnLogout = stopOnLogout;
149149
}
150150

151-
public Long getHeartbeatTimeout() {
151+
public String getHeartbeatTimeout() {
152152
return heartbeatTimeout;
153153
}
154154

155-
public void setHeartbeatTimeout(Long heartbeatTimeout) {
155+
public void setHeartbeatTimeout(String heartbeatTimeout) {
156156
this.heartbeatTimeout = heartbeatTimeout;
157157
}
158158

src/main/java/eu/openanalytics/containerproxy/service/ProxyService.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,11 @@
4242
import eu.openanalytics.containerproxy.event.ProxyStartEvent;
4343
import eu.openanalytics.containerproxy.event.ProxyStopEvent;
4444
import eu.openanalytics.containerproxy.model.runtime.ProvidedParameters;
45+
import eu.openanalytics.containerproxy.model.runtime.runtimevalues.HeartbeatTimeoutKey;
4546
import eu.openanalytics.containerproxy.model.runtime.runtimevalues.ParametersKey;
4647
import eu.openanalytics.containerproxy.model.runtime.runtimevalues.RuntimeValue;
48+
import eu.openanalytics.containerproxy.spec.expression.SpecExpressionContext;
49+
import eu.openanalytics.containerproxy.spec.expression.SpecExpressionResolver;
4750
import eu.openanalytics.containerproxy.util.SuccessOrFailure;
4851
import org.apache.logging.log4j.LogManager;
4952
import org.apache.logging.log4j.Logger;
@@ -259,9 +262,8 @@ public Proxy startProxy(ProxySpec spec, boolean ignoreAccessControl, List<Runtim
259262
if (runtimeValues != null) {
260263
proxy.addRuntimeValues(runtimeValues);
261264
}
262-
if (parametersService.validateRequest(userService.getCurrentAuth(), spec, parameters)) {
263-
proxy.addRuntimeValue(new RuntimeValue(ParametersKey.inst, parameters));
264-
}
265+
266+
runtimeValueService.createRuntimeValues(spec, parameters, proxy);
265267

266268
activeProxies.add(proxy);
267269

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/**
2+
* ContainerProxy
3+
*
4+
* Copyright (C) 2016-2021 Open Analytics
5+
*
6+
* ===========================================================================
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the Apache License as published by
10+
* The Apache Software Foundation, either version 2 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* Apache License for more details.
17+
*
18+
* You should have received a copy of the Apache License
19+
* along with this program. If not, see <http://www.apache.org/licenses/>
20+
*/
21+
package eu.openanalytics.containerproxy.service;
22+
23+
import eu.openanalytics.containerproxy.model.runtime.ProvidedParameters;
24+
import eu.openanalytics.containerproxy.model.runtime.Proxy;
25+
import eu.openanalytics.containerproxy.model.runtime.runtimevalues.HeartbeatTimeoutKey;
26+
import eu.openanalytics.containerproxy.model.runtime.runtimevalues.ParametersKey;
27+
import eu.openanalytics.containerproxy.model.runtime.runtimevalues.RuntimeValue;
28+
import eu.openanalytics.containerproxy.model.spec.ProxySpec;
29+
import eu.openanalytics.containerproxy.spec.expression.SpecExpressionContext;
30+
import eu.openanalytics.containerproxy.spec.expression.SpecExpressionResolver;
31+
import org.springframework.core.env.Environment;
32+
import org.springframework.stereotype.Service;
33+
34+
import javax.inject.Inject;
35+
36+
/**
37+
* Determines the RuntimeValue when a proxy gets started.
38+
*/
39+
@Service
40+
public class RuntimeValueService {
41+
42+
private static final String PROP_TIMEOUT = "proxy.heartbeat-timeout";
43+
44+
private static final Long DEFAULT_TIMEOUT = 60000L;
45+
46+
private long defaultHeartbeatTimeout;
47+
@Inject
48+
private ParametersService parametersService;
49+
50+
@Inject
51+
private SpecExpressionResolver expressionResolver;
52+
53+
@Inject
54+
private Environment environment;
55+
56+
@Inject
57+
private UserService userService;
58+
59+
public void init() {
60+
defaultHeartbeatTimeout = environment.getProperty(PROP_TIMEOUT, Long.class, DEFAULT_TIMEOUT);
61+
}
62+
63+
public void createRuntimeValues(ProxySpec spec, ProvidedParameters parameters, Proxy proxy) throws InvalidParametersException {
64+
if (parametersService.validateRequest(userService.getCurrentAuth(), spec, parameters)) {
65+
proxy.addRuntimeValue(new RuntimeValue(ParametersKey.inst, parameters));
66+
}
67+
SpecExpressionContext context = SpecExpressionContext.create(
68+
proxy,
69+
proxy.getSpec(),
70+
userService.getCurrentAuth().getPrincipal(),
71+
userService.getCurrentAuth().getCredentials());
72+
73+
if (spec.getHeartbeatTimeout() != null) {
74+
Long timeout = expressionResolver.evaluateToLong(spec.getHeartbeatTimeout(), context);
75+
proxy.addRuntimeValue(new RuntimeValue(HeartbeatTimeoutKey.inst, timeout));
76+
} else {
77+
proxy.addRuntimeValue(new RuntimeValue(HeartbeatTimeoutKey.inst, defaultHeartbeatTimeout));
78+
}
79+
}
80+
81+
}

src/main/java/eu/openanalytics/containerproxy/service/hearbeat/ActiveProxiesService.java

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import eu.openanalytics.containerproxy.model.runtime.Proxy;
2424
import eu.openanalytics.containerproxy.model.runtime.ProxyStatus;
25+
import eu.openanalytics.containerproxy.model.runtime.runtimevalues.HeartbeatTimeoutKey;
2526
import eu.openanalytics.containerproxy.service.ProxyService;
2627
import org.apache.logging.log4j.LogManager;
2728
import org.apache.logging.log4j.Logger;
@@ -47,15 +48,11 @@ public class ActiveProxiesService implements IHeartbeatProcessor {
4748

4849
public static final String PROP_RATE = "proxy.heartbeat-rate";
4950
public static final Long DEFAULT_RATE = 10000L;
50-
public static final String PROP_TIMEOUT = "proxy.heartbeat-timeout";
51-
public static final Long DEFAULT_TIMEOUT = 60000L;
5251

5352
private final Logger log = LogManager.getLogger(HeartbeatService.class);
5453

5554
private final Map<String, Long> proxyHeartbeats = Collections.synchronizedMap(new HashMap<>());
5655

57-
private long defaultHeartbeatTimeout;
58-
5956
@Inject
6057
private Environment environment;
6158

@@ -65,7 +62,6 @@ public class ActiveProxiesService implements IHeartbeatProcessor {
6562
@PostConstruct
6663
public void init() {
6764
long cleanupInterval = 2 * environment.getProperty(PROP_RATE, Long.class, DEFAULT_RATE);
68-
defaultHeartbeatTimeout = environment.getProperty(PROP_TIMEOUT, Long.class, DEFAULT_TIMEOUT);
6965
new Timer().schedule(new TimerTask() {
7066
@Override
7167
public void run() {
@@ -102,12 +98,7 @@ private void checkAndReleaseProxy(long currentTimestamp, Proxy proxy) {
10298
return;
10399
}
104100

105-
Long heartbeatTimeout;
106-
if (proxy.getSpec().getHeartbeatTimeout() != null) {
107-
heartbeatTimeout = proxy.getSpec().getHeartbeatTimeout();
108-
} else {
109-
heartbeatTimeout = defaultHeartbeatTimeout;
110-
}
101+
Long heartbeatTimeout = proxy.getRuntimeObject(HeartbeatTimeoutKey.inst);
111102

112103
if (heartbeatTimeout <= 0) {
113104
// heartbeats disabled for this app (or globally)

src/main/java/eu/openanalytics/containerproxy/spec/expression/SpecExpressionResolver.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ public String evaluateToString(String expression, SpecExpressionContext context)
102102
return String.valueOf(evaluate(expression, context));
103103
}
104104

105+
public Long evaluateToLong(String expression, SpecExpressionContext context) {
106+
return Long.valueOf(evaluateToString(expression, context));
107+
}
108+
105109
public Boolean evaluateToBoolean(String expression, SpecExpressionContext context) {
106110
return Boolean.valueOf(evaluateToString(expression, context));
107111
}

0 commit comments

Comments
 (0)