import info.mechyrdia.data.StoragePath
import io.ktor.util.*
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runInterruptible
import kotlinx.coroutines.suspendCancellableCoroutine
-import kotlinx.coroutines.withContext
import kotlinx.serialization.json.*
import java.security.MessageDigest
import java.util.concurrent.ConcurrentHashMap
+import java.util.concurrent.locks.ReentrantLock
import java.util.function.Consumer
import javax.script.Compilable
import javax.script.CompiledScript
import javax.script.ScriptEngineManager
import javax.script.SimpleBindings
+import kotlin.concurrent.withLock
import kotlin.coroutines.*
object PreProcessorTemplateLoader {
}
object PreProcessorScriptLoader {
- private val scriptEngine = ThreadLocal.withInitial { ScriptEngineManager().getEngineByExtension("groovy") }
+ private val scriptEngine = ScriptEngineManager().getEngineByExtension("groovy")
+ private val scriptEngineSync = ReentrantLock(true)
private val hasher = ThreadLocal.withInitial { MessageDigest.getInstance("SHA-256") }
private val cache = ConcurrentHashMap<String, CompiledScript>()
val scriptFile = StoragePath.scriptDir / "$name.groovy"
val script = FileStorage.instance.readFile(scriptFile) ?: return null
- val digest = hex(hasher.get().digest(script))
- return withContext(Dispatchers.IO) {
+ return runInterruptible(Dispatchers.IO) {
+ val digest = hex(hasher.get().digest(script))
+
cache.getOrPut(digest) {
- (scriptEngine.get() as Compilable).compile(String(script))
+ scriptEngineSync.withLock {
+ (scriptEngine as Compilable).compile(String(script))
+ }
}
}
}
bindings["ctx"] = PreProcessorScriptVarContext { jsonToGroovy(env.context[it].toPreProcessJson()) }
bindings["finish"] = Consumer<Any?>(continuation::resume)
- script.eval(bindings)
+ scriptEngineSync.withLock {
+ script.eval(bindings)
+ }
}
}