diff --git a/sentry-log4j2/src/test/kotlin/io/sentry/log4j2/SentryAppenderTest.kt b/sentry-log4j2/src/test/kotlin/io/sentry/log4j2/SentryAppenderTest.kt index 3786555a61..2713bb7f17 100644 --- a/sentry-log4j2/src/test/kotlin/io/sentry/log4j2/SentryAppenderTest.kt +++ b/sentry-log4j2/src/test/kotlin/io/sentry/log4j2/SentryAppenderTest.kt @@ -78,6 +78,7 @@ class SentryAppenderTest { @BeforeTest fun `clear MDC`() { ThreadContext.clearAll() + Sentry.close() } @Test diff --git a/sentry-quartz/api/sentry-quartz.api b/sentry-quartz/api/sentry-quartz.api index 23fce49e7d..21ca2abca6 100644 --- a/sentry-quartz/api/sentry-quartz.api +++ b/sentry-quartz/api/sentry-quartz.api @@ -5,6 +5,7 @@ public final class io/sentry/quartz/BuildConfig { public final class io/sentry/quartz/SentryJobListener : org/quartz/JobListener { public static final field SENTRY_CHECK_IN_ID_KEY Ljava/lang/String; + public static final field SENTRY_LIFECYCLE_TOKEN_KEY Ljava/lang/String; public static final field SENTRY_SLUG_KEY Ljava/lang/String; public fun ()V public fun (Lio/sentry/IScopes;)V diff --git a/sentry-quartz/src/main/java/io/sentry/quartz/SentryJobListener.java b/sentry-quartz/src/main/java/io/sentry/quartz/SentryJobListener.java index f9c22022cc..03f1acbbed 100644 --- a/sentry-quartz/src/main/java/io/sentry/quartz/SentryJobListener.java +++ b/sentry-quartz/src/main/java/io/sentry/quartz/SentryJobListener.java @@ -4,10 +4,12 @@ import io.sentry.CheckIn; import io.sentry.CheckInStatus; import io.sentry.IScopes; +import io.sentry.ISentryLifecycleToken; import io.sentry.ScopesAdapter; import io.sentry.SentryIntegrationPackageStorage; import io.sentry.SentryLevel; import io.sentry.protocol.SentryId; +import io.sentry.util.LifecycleHelper; import io.sentry.util.Objects; import io.sentry.util.TracingUtils; import org.jetbrains.annotations.ApiStatus; @@ -23,6 +25,7 @@ public final class SentryJobListener implements JobListener { public static final String SENTRY_CHECK_IN_ID_KEY = "sentry-checkin-id"; public static final String SENTRY_SLUG_KEY = "sentry-slug"; + public static final String SENTRY_LIFECYCLE_TOKEN_KEY = "sentry-lifecycle"; private final @NotNull IScopes scopes; @@ -49,13 +52,14 @@ public void jobToBeExecuted(final @NotNull JobExecutionContext context) { if (maybeSlug == null) { return; } - scopes.pushScope(); + final @NotNull ISentryLifecycleToken lifecycleToken = scopes.pushIsolationScope(); TracingUtils.startNewTrace(scopes); final @NotNull String slug = maybeSlug; final @NotNull CheckIn checkIn = new CheckIn(slug, CheckInStatus.IN_PROGRESS); final @NotNull SentryId checkInId = scopes.captureCheckIn(checkIn); context.put(SENTRY_CHECK_IN_ID_KEY, checkInId); context.put(SENTRY_SLUG_KEY, slug); + context.put(SENTRY_LIFECYCLE_TOKEN_KEY, lifecycleToken); } catch (Throwable t) { scopes .getOptions() @@ -103,7 +107,7 @@ public void jobWasExecuted(JobExecutionContext context, JobExecutionException jo .getLogger() .log(SentryLevel.ERROR, "Unable to capture check-in in jobWasExecuted.", t); } finally { - scopes.popScope(); + LifecycleHelper.close(context.get(SENTRY_LIFECYCLE_TOKEN_KEY)); } } } diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/checkin/SentryCheckInAdvice.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/checkin/SentryCheckInAdvice.java index 4a366a8b01..e51647cba8 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/checkin/SentryCheckInAdvice.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/checkin/SentryCheckInAdvice.java @@ -5,6 +5,7 @@ import io.sentry.CheckInStatus; import io.sentry.DateUtils; import io.sentry.IScopes; +import io.sentry.ISentryLifecycleToken; import io.sentry.ScopesAdapter; import io.sentry.SentryLevel; import io.sentry.protocol.SentryId; @@ -86,7 +87,7 @@ public Object invoke(final @NotNull MethodInvocation invocation) throws Throwabl return invocation.proceed(); } - scopes.pushScope(); + final @NotNull ISentryLifecycleToken lifecycleToken = scopes.pushIsolationScope(); TracingUtils.startNewTrace(scopes); @Nullable SentryId checkInId = null; @@ -106,7 +107,7 @@ public Object invoke(final @NotNull MethodInvocation invocation) throws Throwabl CheckIn checkIn = new CheckIn(checkInId, monitorSlug, status); checkIn.setDuration(DateUtils.millisToSeconds(System.currentTimeMillis() - startTime)); scopes.captureCheckIn(checkIn); - scopes.popScope(); + lifecycleToken.close(); } } diff --git a/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/SentryCheckInAdviceTest.kt b/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/SentryCheckInAdviceTest.kt index 5d093f50f1..e87b5f5b26 100644 --- a/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/SentryCheckInAdviceTest.kt +++ b/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/SentryCheckInAdviceTest.kt @@ -3,6 +3,7 @@ package io.sentry.spring.jakarta import io.sentry.CheckIn import io.sentry.CheckInStatus import io.sentry.IScopes +import io.sentry.ISentryLifecycleToken import io.sentry.Sentry import io.sentry.SentryOptions import io.sentry.protocol.SentryId @@ -56,10 +57,13 @@ class SentryCheckInAdviceTest { @Autowired lateinit var scopes: IScopes + val lifecycleToken = mock() + @BeforeTest fun setup() { reset(scopes) whenever(scopes.options).thenReturn(SentryOptions()) + whenever(scopes.pushIsolationScope()).thenReturn(lifecycleToken) } @Test @@ -79,10 +83,10 @@ class SentryCheckInAdviceTest { assertEquals("monitor_slug_1", doneCheckIn.monitorSlug) assertEquals(CheckInStatus.OK.apiName(), doneCheckIn.status) - val order = inOrder(scopes) - order.verify(scopes).pushScope() + val order = inOrder(scopes, lifecycleToken) + order.verify(scopes).pushIsolationScope() order.verify(scopes, times(2)).captureCheckIn(any()) - order.verify(scopes).popScope() + order.verify(lifecycleToken).close() } @Test @@ -103,10 +107,10 @@ class SentryCheckInAdviceTest { assertEquals("monitor_slug_1e", doneCheckIn.monitorSlug) assertEquals(CheckInStatus.ERROR.apiName(), doneCheckIn.status) - val order = inOrder(scopes) - order.verify(scopes).pushScope() + val order = inOrder(scopes, lifecycleToken) + order.verify(scopes).pushIsolationScope() order.verify(scopes, times(2)).captureCheckIn(any()) - order.verify(scopes).popScope() + order.verify(lifecycleToken).close() } @Test @@ -123,10 +127,10 @@ class SentryCheckInAdviceTest { assertEquals(CheckInStatus.OK.apiName(), doneCheckIn.status) assertNotNull(doneCheckIn.duration) - val order = inOrder(scopes) - order.verify(scopes).pushScope() + val order = inOrder(scopes, lifecycleToken) + order.verify(scopes).pushIsolationScope() order.verify(scopes).captureCheckIn(any()) - order.verify(scopes).popScope() + order.verify(lifecycleToken).close() } @Test @@ -144,10 +148,10 @@ class SentryCheckInAdviceTest { assertEquals(CheckInStatus.ERROR.apiName(), doneCheckIn.status) assertNotNull(doneCheckIn.duration) - val order = inOrder(scopes) - order.verify(scopes).pushScope() + val order = inOrder(scopes, lifecycleToken) + order.verify(scopes).pushIsolationScope() order.verify(scopes).captureCheckIn(any()) - order.verify(scopes).popScope() + order.verify(lifecycleToken).close() } @Test @@ -178,10 +182,10 @@ class SentryCheckInAdviceTest { assertEquals(CheckInStatus.OK.apiName(), doneCheckIn.status) assertNotNull(doneCheckIn.duration) - val order = inOrder(scopes) - order.verify(scopes).pushScope() + val order = inOrder(scopes, lifecycleToken) + order.verify(scopes).pushIsolationScope() order.verify(scopes).captureCheckIn(any()) - order.verify(scopes).popScope() + order.verify(lifecycleToken).close() } @Test @@ -198,10 +202,10 @@ class SentryCheckInAdviceTest { assertEquals(CheckInStatus.OK.apiName(), doneCheckIn.status) assertNotNull(doneCheckIn.duration) - val order = inOrder(scopes) - order.verify(scopes).pushScope() + val order = inOrder(scopes, lifecycleToken) + order.verify(scopes).pushIsolationScope() order.verify(scopes).captureCheckIn(any()) - order.verify(scopes).popScope() + order.verify(lifecycleToken).close() } @Test @@ -218,10 +222,10 @@ class SentryCheckInAdviceTest { assertEquals(CheckInStatus.OK.apiName(), doneCheckIn.status) assertNotNull(doneCheckIn.duration) - val order = inOrder(scopes) - order.verify(scopes).pushScope() + val order = inOrder(scopes, lifecycleToken) + order.verify(scopes).pushIsolationScope() order.verify(scopes).captureCheckIn(any()) - order.verify(scopes).popScope() + order.verify(lifecycleToken).close() } @Configuration diff --git a/sentry-spring/src/main/java/io/sentry/spring/checkin/SentryCheckInAdvice.java b/sentry-spring/src/main/java/io/sentry/spring/checkin/SentryCheckInAdvice.java index edae74c2ac..9e59093b16 100644 --- a/sentry-spring/src/main/java/io/sentry/spring/checkin/SentryCheckInAdvice.java +++ b/sentry-spring/src/main/java/io/sentry/spring/checkin/SentryCheckInAdvice.java @@ -5,6 +5,7 @@ import io.sentry.CheckInStatus; import io.sentry.DateUtils; import io.sentry.IScopes; +import io.sentry.ISentryLifecycleToken; import io.sentry.ScopesAdapter; import io.sentry.SentryLevel; import io.sentry.protocol.SentryId; @@ -89,7 +90,7 @@ public Object invoke(final @NotNull MethodInvocation invocation) throws Throwabl return invocation.proceed(); } - scopes.pushScope(); + final @NotNull ISentryLifecycleToken lifecycleToken = scopes.pushIsolationScope(); TracingUtils.startNewTrace(scopes); @Nullable SentryId checkInId = null; @@ -109,7 +110,7 @@ public Object invoke(final @NotNull MethodInvocation invocation) throws Throwabl CheckIn checkIn = new CheckIn(checkInId, monitorSlug, status); checkIn.setDuration(DateUtils.millisToSeconds(System.currentTimeMillis() - startTime)); scopes.captureCheckIn(checkIn); - scopes.popScope(); + lifecycleToken.close(); } } diff --git a/sentry-spring/src/test/kotlin/io/sentry/spring/SentryCheckInAdviceTest.kt b/sentry-spring/src/test/kotlin/io/sentry/spring/SentryCheckInAdviceTest.kt index 23807e1fd9..57bd293756 100644 --- a/sentry-spring/src/test/kotlin/io/sentry/spring/SentryCheckInAdviceTest.kt +++ b/sentry-spring/src/test/kotlin/io/sentry/spring/SentryCheckInAdviceTest.kt @@ -3,6 +3,7 @@ package io.sentry.spring import io.sentry.CheckIn import io.sentry.CheckInStatus import io.sentry.IScopes +import io.sentry.ISentryLifecycleToken import io.sentry.Sentry import io.sentry.SentryOptions import io.sentry.protocol.SentryId @@ -57,10 +58,13 @@ class SentryCheckInAdviceTest { @Autowired lateinit var scopes: IScopes + val lifecycleToken = mock() + @BeforeTest fun setup() { reset(scopes) whenever(scopes.options).thenReturn(SentryOptions()) + whenever(scopes.pushIsolationScope()).thenReturn(lifecycleToken) } @Test @@ -80,10 +84,10 @@ class SentryCheckInAdviceTest { assertEquals("monitor_slug_1", doneCheckIn.monitorSlug) assertEquals(CheckInStatus.OK.apiName(), doneCheckIn.status) - val order = inOrder(scopes) - order.verify(scopes).pushScope() + val order = inOrder(scopes, lifecycleToken) + order.verify(scopes).pushIsolationScope() order.verify(scopes, times(2)).captureCheckIn(any()) - order.verify(scopes).popScope() + order.verify(lifecycleToken).close() } @Test @@ -104,10 +108,10 @@ class SentryCheckInAdviceTest { assertEquals("monitor_slug_1e", doneCheckIn.monitorSlug) assertEquals(CheckInStatus.ERROR.apiName(), doneCheckIn.status) - val order = inOrder(scopes) - order.verify(scopes).pushScope() + val order = inOrder(scopes, lifecycleToken) + order.verify(scopes).pushIsolationScope() order.verify(scopes, times(2)).captureCheckIn(any()) - order.verify(scopes).popScope() + order.verify(lifecycleToken).close() } @Test @@ -124,10 +128,10 @@ class SentryCheckInAdviceTest { assertEquals(CheckInStatus.OK.apiName(), doneCheckIn.status) assertNotNull(doneCheckIn.duration) - val order = inOrder(scopes) - order.verify(scopes).pushScope() + val order = inOrder(scopes, lifecycleToken) + order.verify(scopes).pushIsolationScope() order.verify(scopes).captureCheckIn(any()) - order.verify(scopes).popScope() + order.verify(lifecycleToken).close() } @Test @@ -145,10 +149,10 @@ class SentryCheckInAdviceTest { assertEquals(CheckInStatus.ERROR.apiName(), doneCheckIn.status) assertNotNull(doneCheckIn.duration) - val order = inOrder(scopes) - order.verify(scopes).pushScope() + val order = inOrder(scopes, lifecycleToken) + order.verify(scopes).pushIsolationScope() order.verify(scopes).captureCheckIn(any()) - order.verify(scopes).popScope() + order.verify(lifecycleToken).close() } @Test @@ -160,9 +164,9 @@ class SentryCheckInAdviceTest { assertEquals(1, result) assertEquals(0, checkInCaptor.allValues.size) - verify(scopes, never()).pushScope() + verify(scopes, never()).pushIsolationScope() verify(scopes, never()).captureCheckIn(any()) - verify(scopes, never()).popScope() + verify(lifecycleToken, never()).close() } @Test @@ -179,10 +183,10 @@ class SentryCheckInAdviceTest { assertEquals(CheckInStatus.OK.apiName(), doneCheckIn.status) assertNotNull(doneCheckIn.duration) - val order = inOrder(scopes) - order.verify(scopes).pushScope() + val order = inOrder(scopes, lifecycleToken) + order.verify(scopes).pushIsolationScope() order.verify(scopes).captureCheckIn(any()) - order.verify(scopes).popScope() + order.verify(lifecycleToken).close() } @Test @@ -199,10 +203,10 @@ class SentryCheckInAdviceTest { assertEquals(CheckInStatus.OK.apiName(), doneCheckIn.status) assertNotNull(doneCheckIn.duration) - val order = inOrder(scopes) - order.verify(scopes).pushScope() + val order = inOrder(scopes, lifecycleToken) + order.verify(scopes).pushIsolationScope() order.verify(scopes).captureCheckIn(any()) - order.verify(scopes).popScope() + order.verify(lifecycleToken).close() } @Test @@ -219,10 +223,10 @@ class SentryCheckInAdviceTest { assertEquals(CheckInStatus.OK.apiName(), doneCheckIn.status) assertNotNull(doneCheckIn.duration) - val order = inOrder(scopes) - order.verify(scopes).pushScope() + val order = inOrder(scopes, lifecycleToken) + order.verify(scopes).pushIsolationScope() order.verify(scopes).captureCheckIn(any()) - order.verify(scopes).popScope() + order.verify(lifecycleToken).close() } @Configuration diff --git a/sentry/src/main/java/io/sentry/util/CheckInUtils.java b/sentry/src/main/java/io/sentry/util/CheckInUtils.java index 6719e24839..d42cf4edf4 100644 --- a/sentry/src/main/java/io/sentry/util/CheckInUtils.java +++ b/sentry/src/main/java/io/sentry/util/CheckInUtils.java @@ -4,6 +4,7 @@ import io.sentry.CheckInStatus; import io.sentry.DateUtils; import io.sentry.IScopes; +import io.sentry.ISentryLifecycleToken; import io.sentry.MonitorConfig; import io.sentry.Sentry; import io.sentry.protocol.SentryId; @@ -30,12 +31,11 @@ public static U withCheckIn( final @Nullable MonitorConfig monitorConfig, final @NotNull Callable callable) throws Exception { + final @NotNull ISentryLifecycleToken lifecycleToken = Sentry.pushIsolationScope(); final @NotNull IScopes scopes = Sentry.getCurrentScopes(); final long startTime = System.currentTimeMillis(); boolean didError = false; - // TODO fork instead - scopes.pushScope(); TracingUtils.startNewTrace(scopes); CheckIn inProgressCheckIn = new CheckIn(monitorSlug, CheckInStatus.IN_PROGRESS); @@ -53,7 +53,7 @@ public static U withCheckIn( CheckIn checkIn = new CheckIn(checkInId, monitorSlug, status); checkIn.setDuration(DateUtils.millisToSeconds(System.currentTimeMillis() - startTime)); scopes.captureCheckIn(checkIn); - scopes.popScope(); + lifecycleToken.close(); } } diff --git a/sentry/src/main/java/io/sentry/util/LifecycleHelper.java b/sentry/src/main/java/io/sentry/util/LifecycleHelper.java new file mode 100644 index 0000000000..4a029f620c --- /dev/null +++ b/sentry/src/main/java/io/sentry/util/LifecycleHelper.java @@ -0,0 +1,15 @@ +package io.sentry.util; + +import io.sentry.ISentryLifecycleToken; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class LifecycleHelper { + + public static void close(final @Nullable Object tokenObject) { + if (tokenObject != null && tokenObject instanceof ISentryLifecycleToken) { + final @NotNull ISentryLifecycleToken token = (ISentryLifecycleToken) tokenObject; + token.close(); + } + } +} diff --git a/sentry/src/test/java/io/sentry/util/CheckInUtilsTest.kt b/sentry/src/test/java/io/sentry/util/CheckInUtilsTest.kt index 9f330348b0..7058083ac9 100644 --- a/sentry/src/test/java/io/sentry/util/CheckInUtilsTest.kt +++ b/sentry/src/test/java/io/sentry/util/CheckInUtilsTest.kt @@ -3,6 +3,7 @@ package io.sentry.util import io.sentry.CheckInStatus import io.sentry.HubScopesWrapper import io.sentry.IScopes +import io.sentry.ISentryLifecycleToken import io.sentry.MonitorConfig import io.sentry.MonitorSchedule import io.sentry.MonitorScheduleUnit @@ -58,16 +59,21 @@ class CheckInUtilsTest { fun `sends check-in for wrapped supplier`() { Mockito.mockStatic(Sentry::class.java).use { sentry -> val scopes = mock() + val lifecycleToken = mock() sentry.`when` { Sentry.getCurrentScopes() }.thenReturn(scopes) sentry.`when` { Sentry.getCurrentHub() }.thenReturn(HubScopesWrapper(scopes)) + sentry.`when` { Sentry.pushIsolationScope() }.then { + scopes.pushIsolationScope() + lifecycleToken + } whenever(scopes.options).thenReturn(SentryOptions()) val returnValue = CheckInUtils.withCheckIn("monitor-1") { return@withCheckIn "test1" } assertEquals("test1", returnValue) - inOrder(scopes) { - verify(scopes).pushScope() + inOrder(scopes, lifecycleToken) { + verify(scopes).pushIsolationScope() verify(scopes).configureScope(any()) verify(scopes).captureCheckIn( check { @@ -81,7 +87,7 @@ class CheckInUtilsTest { assertEquals(CheckInStatus.OK.apiName(), it.status) } ) - verify(scopes).popScope() + verify(lifecycleToken).close() } } } @@ -90,8 +96,13 @@ class CheckInUtilsTest { fun `sends check-in for wrapped supplier with exception`() { Mockito.mockStatic(Sentry::class.java).use { sentry -> val scopes = mock() + val lifecycleToken = mock() sentry.`when` { Sentry.getCurrentScopes() }.thenReturn(scopes) sentry.`when` { Sentry.getCurrentHub() }.thenReturn(HubScopesWrapper(scopes)) + sentry.`when` { Sentry.pushIsolationScope() }.then { + scopes.pushIsolationScope() + lifecycleToken + } try { CheckInUtils.withCheckIn("monitor-1") { @@ -102,8 +113,8 @@ class CheckInUtilsTest { assertEquals("thrown on purpose", e.message) } - inOrder(scopes) { - verify(scopes).pushScope() + inOrder(scopes, lifecycleToken) { + verify(scopes).pushIsolationScope() verify(scopes).configureScope(any()) verify(scopes).captureCheckIn( check { @@ -117,7 +128,7 @@ class CheckInUtilsTest { assertEquals(CheckInStatus.ERROR.apiName(), it.status) } ) - verify(scopes).popScope() + verify(lifecycleToken).close() } } } @@ -126,8 +137,13 @@ class CheckInUtilsTest { fun `sends check-in for wrapped supplier with upsert`() { Mockito.mockStatic(Sentry::class.java).use { sentry -> val scopes = mock() + val lifecycleToken = mock() sentry.`when` { Sentry.getCurrentScopes() }.thenReturn(scopes) sentry.`when` { Sentry.getCurrentHub() }.thenReturn(HubScopesWrapper(scopes)) + sentry.`when` { Sentry.pushIsolationScope() }.then { + scopes.pushIsolationScope() + lifecycleToken + } whenever(scopes.options).thenReturn(SentryOptions()) val monitorConfig = MonitorConfig(MonitorSchedule.interval(7, MonitorScheduleUnit.DAY)) val returnValue = CheckInUtils.withCheckIn("monitor-1", monitorConfig) { @@ -135,8 +151,8 @@ class CheckInUtilsTest { } assertEquals("test1", returnValue) - inOrder(scopes) { - verify(scopes).pushScope() + inOrder(scopes, lifecycleToken) { + verify(scopes).pushIsolationScope() verify(scopes).configureScope(any()) verify(scopes).captureCheckIn( check { @@ -151,7 +167,7 @@ class CheckInUtilsTest { assertEquals(CheckInStatus.OK.apiName(), it.status) } ) - verify(scopes).popScope() + verify(lifecycleToken).close() } } } @@ -160,8 +176,13 @@ class CheckInUtilsTest { fun `sends check-in for wrapped supplier with upsert and thresholds`() { Mockito.mockStatic(Sentry::class.java).use { sentry -> val scopes = mock() + val lifecycleToken = mock() sentry.`when` { Sentry.getCurrentScopes() }.thenReturn(scopes) sentry.`when` { Sentry.getCurrentHub() }.thenReturn(HubScopesWrapper(scopes)) + sentry.`when` { Sentry.pushIsolationScope() }.then { + scopes.pushIsolationScope() + lifecycleToken + } whenever(scopes.options).thenReturn(SentryOptions()) val monitorConfig = MonitorConfig(MonitorSchedule.interval(7, MonitorScheduleUnit.DAY)).apply { failureIssueThreshold = 10 @@ -172,8 +193,8 @@ class CheckInUtilsTest { } assertEquals("test1", returnValue) - inOrder(scopes) { - verify(scopes).pushScope() + inOrder(scopes, lifecycleToken) { + verify(scopes).pushIsolationScope() verify(scopes).configureScope(any()) verify(scopes).captureCheckIn( check { @@ -188,7 +209,7 @@ class CheckInUtilsTest { assertEquals(CheckInStatus.OK.apiName(), it.status) } ) - verify(scopes).popScope() + verify(lifecycleToken).close() } } }