Synchronize doEvalScript and doRelease operations in MvelInvokeService

This commit is contained in:
ViacheslavKlimov 2022-11-14 19:02:52 +02:00
parent dee81fea26
commit 1283093681
2 changed files with 23 additions and 10 deletions

View File

@ -625,7 +625,7 @@ mvel:
max_black_list_duration_sec: "${MVEL_MAX_BLACKLIST_DURATION_SEC:60}" max_black_list_duration_sec: "${MVEL_MAX_BLACKLIST_DURATION_SEC:60}"
# Specify thread pool size for javascript executor service # Specify thread pool size for javascript executor service
thread_pool_size: "${MVEL_THREAD_POOL_SIZE:50}" thread_pool_size: "${MVEL_THREAD_POOL_SIZE:50}"
compiled_scripts_cache_size: "${MVEL_COMPILED_SCRIPTS_CACHE_SIZE:2000}" compiled_scripts_cache_size: "${MVEL_COMPILED_SCRIPTS_CACHE_SIZE:1000}"
stats: stats:
enabled: "${TB_MVEL_STATS_ENABLED:false}" enabled: "${TB_MVEL_STATS_ENABLED:false}"
print_interval_ms: "${TB_MVEL_STATS_PRINT_INTERVAL_MS:10000}" print_interval_ms: "${TB_MVEL_STATS_PRINT_INTERVAL_MS:10000}"

View File

@ -53,6 +53,8 @@ import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@Slf4j @Slf4j
@ -100,11 +102,13 @@ public class DefaultMvelInvokeService extends AbstractScriptInvokeService implem
@Value("${mvel.max_memory_limit_mb:8}") @Value("${mvel.max_memory_limit_mb:8}")
private long maxMemoryLimitMb; private long maxMemoryLimitMb;
@Value("${mvel.compiled_scripts_cache_size:2000}") @Value("${mvel.compiled_scripts_cache_size:1000}")
private int compiledScriptsCacheSize; private int compiledScriptsCacheSize;
private ListeningExecutorService executor; private ListeningExecutorService executor;
private final Lock lock = new ReentrantLock();
protected DefaultMvelInvokeService(Optional<TbApiUsageStateClient> apiUsageStateClient, Optional<TbApiUsageReportClient> apiUsageReportClient) { protected DefaultMvelInvokeService(Optional<TbApiUsageStateClient> apiUsageStateClient, Optional<TbApiUsageReportClient> apiUsageReportClient) {
super(apiUsageStateClient, apiUsageReportClient); super(apiUsageStateClient, apiUsageReportClient);
} }
@ -166,10 +170,15 @@ public class DefaultMvelInvokeService extends AbstractScriptInvokeService implem
compiledScriptsCache.get(scriptHash, k -> { compiledScriptsCache.get(scriptHash, k -> {
return compileScript(scriptBody); return compileScript(scriptBody);
}); });
lock.lock();
try {
scriptIdToHash.put(scriptId, scriptHash); scriptIdToHash.put(scriptId, scriptHash);
scriptMap.computeIfAbsent(scriptHash, k -> { scriptMap.computeIfAbsent(scriptHash, k -> {
return new MvelScript(scriptBody, argNames); return new MvelScript(scriptBody, argNames);
}); });
} finally {
lock.unlock();
}
return scriptId; return scriptId;
} catch (Exception e) { } catch (Exception e) {
throw new TbScriptException(scriptId, TbScriptException.ErrorCode.COMPILATION, scriptBody, e); throw new TbScriptException(scriptId, TbScriptException.ErrorCode.COMPILATION, scriptBody, e);
@ -203,12 +212,16 @@ public class DefaultMvelInvokeService extends AbstractScriptInvokeService implem
protected void doRelease(UUID scriptId) throws Exception { protected void doRelease(UUID scriptId) throws Exception {
String scriptHash = scriptIdToHash.remove(scriptId); String scriptHash = scriptIdToHash.remove(scriptId);
if (scriptHash != null) { if (scriptHash != null) {
if (scriptIdToHash.containsValue(scriptHash)) { lock.lock();
return; try {
} if (!scriptIdToHash.containsValue(scriptHash)) {
scriptMap.remove(scriptHash); scriptMap.remove(scriptHash);
compiledScriptsCache.invalidate(scriptHash); compiledScriptsCache.invalidate(scriptHash);
} }
} finally {
lock.unlock();
}
}
} }
private Serializable compileScript(String scriptBody) { private Serializable compileScript(String scriptBody) {