ScriptProfile: Recover from closed context for JS Scripting (#4437)

Co-authored-by: J-N-K <github@klug.nrw>
Signed-off-by: Florian Hotze <dev@florianhotze.com>
This commit is contained in:
Florian Hotze 2024-11-06 21:20:34 +01:00 committed by GitHub
parent a31e8376a4
commit 4eec4a3e45
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 29 additions and 1 deletions

View File

@ -214,6 +214,18 @@ public class ScriptTransformationService implements TransformationService, Confi
return result == null ? null : result.toString();
} catch (ScriptException e) {
throw new TransformationException("Failed to execute script.", e);
} catch (IllegalStateException e) {
// ISE thrown by JS Scripting if script engine already closed
if ("The Context is already closed.".equals(e.getMessage())) {
logger.warn(
"Script engine context {} is already closed, this should not happen. Recreating script engine.",
scriptUid);
scriptCache.remove(scriptUid);
return transform(function, source);
} else {
// rethrow
throw e;
}
}
} finally {
scriptRecord.lock.unlock();

View File

@ -37,6 +37,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import org.openhab.core.config.core.ConfigDescriptionRegistry;
import org.openhab.core.test.java.JavaTest;
import org.openhab.core.transform.Transformation;
import org.openhab.core.transform.TransformationException;
import org.openhab.core.transform.TransformationRegistry;
@ -49,7 +50,7 @@ import org.openhab.core.transform.TransformationRegistry;
@NonNullByDefault
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class ScriptTransformationServiceTest {
public class ScriptTransformationServiceTest extends JavaTest {
private static final String SCRIPT_LANGUAGE = "customDsl";
private static final String SCRIPT_UID = "scriptUid." + SCRIPT_LANGUAGE;
private static final String INVALID_SCRIPT_UID = "invalidScriptUid";
@ -189,6 +190,21 @@ public class ScriptTransformationServiceTest {
assertThat(e.getCause().getMessage(), is("exception"));
}
@Test
public void recoversFromClosedScriptContext() throws ScriptException, TransformationException {
when(scriptEngine.eval(SCRIPT)).thenThrow(new IllegalStateException("The Context is already closed."))
.thenReturn(SCRIPT_OUTPUT);
setupInterceptedLogger(ScriptTransformationService.class, LogLevel.WARN);
String returnValue = Objects.requireNonNull(service.transform(SCRIPT_UID, "input"));
assertThat(returnValue, is(SCRIPT_OUTPUT));
stopInterceptedLogger(ScriptTransformationService.class);
assertLogMessage(ScriptTransformationService.class, LogLevel.WARN, "Script engine context " + SCRIPT_UID
+ " is already closed, this should not happen. Recreating script engine.");
}
@Test
public void inlineScriptProperlyProcessed() throws TransformationException, ScriptException {
service.transform(INLINE_SCRIPT, "input");