Skip to content

Commit 0aa2074

Browse files
committed
implement defaultRemoteResourceResolverProvider instead
1 parent 4b80f54 commit 0aa2074

File tree

6 files changed

+99
-189
lines changed

6 files changed

+99
-189
lines changed

plugins/core/core/src/software/aws/toolkits/core/utils/RemoteResourceResolver.kt

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33

44
package software.aws.toolkits.core.utils
55

6-
import com.intellij.util.io.HttpRequests
76
import java.io.FileInputStream
87
import java.io.InputStream
8+
import java.net.HttpURLConnection
9+
import java.net.URL
910
import java.nio.file.Files
1011
import java.nio.file.Path
1112
import java.nio.file.StandardCopyOption
@@ -18,6 +19,8 @@ import java.util.concurrent.atomic.AtomicBoolean
1819

1920
interface RemoteResourceResolver {
2021
fun resolve(resource: RemoteResource): CompletionStage<Path>
22+
fun checkForUpdates(endpoint: String, eTagProvider: ETagProvider): UpdateCheckResult
23+
fun getLocalResourcePath(filename: String): Path?
2124
}
2225
interface RemoteResolveParser {
2326
fun canBeParsed(data: InputStream): Boolean
@@ -43,12 +46,12 @@ class DefaultRemoteResourceResolver(
4346

4447
override fun resolve(resource: RemoteResource): CompletionStage<Path> = executor(Callable { internalResolve(resource) })
4548

46-
fun getLocalResourcePath(resourceName: String): Path? {
47-
val expectedLocation = cacheBasePath.resolve(resourceName)
49+
override fun getLocalResourcePath(filename: String): Path? {
50+
val expectedLocation = cacheBasePath.resolve(filename)
4851
return expectedLocation.existsOrNull()
4952
}
5053

51-
fun checkForUpdates(endpoint: String, eTagProvider: ETagProvider): UpdateCheckResult {
54+
override fun checkForUpdates(endpoint: String, eTagProvider: ETagProvider): UpdateCheckResult {
5255
val hasETagUpdate = updateETags(eTagProvider, endpoint)
5356
// for when we need to notify on first poll even when there's no new ETag
5457
if (isFirstPoll.compareAndSet(true, false) && !hasETagUpdate) {
@@ -124,13 +127,18 @@ class DefaultRemoteResourceResolver(
124127

125128
private fun getEndpointETag(endpoint: String): String =
126129
try {
127-
HttpRequests.request(endpoint)
128-
.userAgent("AWS Toolkit for JetBrains")
129-
.connect { request ->
130-
request.connection.headerFields["ETag"]?.firstOrNull().orEmpty()
131-
}
130+
val url = URL(endpoint)
131+
(url.openConnection() as HttpURLConnection).let { connection ->
132+
connection.requestMethod = "HEAD"
133+
connection.setRequestProperty("User-Agent", "AWS Toolkit for JetBrains")
134+
connection.connect()
135+
136+
val eTag = connection.getHeaderField("ETag") ?: ""
137+
connection.disconnect()
138+
eTag
139+
}
132140
} catch (e: Exception) {
133-
LOG.warn { "Failed to fetch notification ETag: $e.message" }
141+
LOG.warn { "Failed to fetch notification ETag: ${e.message}" }
134142
throw e
135143
}
136144

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,20 @@ import kotlinx.coroutines.delay
1414
import kotlinx.coroutines.runBlocking
1515
import software.aws.toolkits.core.utils.RemoteResolveParser
1616
import software.aws.toolkits.core.utils.RemoteResource
17+
import software.aws.toolkits.core.utils.UpdateCheckResult
1718
import software.aws.toolkits.core.utils.getLogger
1819
import software.aws.toolkits.core.utils.info
1920
import software.aws.toolkits.core.utils.warn
21+
import software.aws.toolkits.jetbrains.core.DefaultRemoteResourceResolverProvider
22+
import software.aws.toolkits.jetbrains.core.RemoteResourceResolverProvider
2023
import software.aws.toolkits.telemetry.Component
2124
import software.aws.toolkits.telemetry.ToolkitTelemetry
2225
import java.io.InputStream
2326
import java.time.Duration
2427

2528
private const val MAX_RETRIES = 3
2629
private const val RETRY_DELAY_MS = 1000L
30+
internal const val FILENAME = "notifications.json"
2731

2832
object NotificationFileValidator : RemoteResolveParser {
2933
override fun canBeParsed(data: InputStream): Boolean =
@@ -45,9 +49,9 @@ internal final class NotificationPollingService : Disposable {
4549
private val observers = mutableListOf<() -> Unit>()
4650
private val alarm = AlarmFactory.getInstance().create(Alarm.ThreadToUse.POOLED_THREAD, this)
4751
private val pollingIntervalMs = Duration.ofMinutes(10).toMillis()
48-
private val resourceResolver: NotificationResourceResolverProvider = DefaultNotificationResourceResolverProvider()
52+
private val resourceResolver: RemoteResourceResolverProvider = DefaultRemoteResourceResolverProvider()
4953
private val notificationsResource = object : RemoteResource {
50-
override val name: String = "notifications.json"
54+
override val name: String = FILENAME
5155
override val urls: List<String> = listOf(NotificationEndpoint.getEndpoint())
5256
override val remoteResolveParser: RemoteResolveParser = NotificationFileValidator
5357
override val ttl: Duration = Duration.ofMillis(1)
@@ -71,7 +75,12 @@ internal final class NotificationPollingService : Disposable {
7175
while (retryCount < MAX_RETRIES) {
7276
LOG.info { "Polling for notifications" }
7377
try {
74-
when (resourceResolver.get().checkForUpdates()) {
78+
when (
79+
resourceResolver.get().checkForUpdates(
80+
NotificationEndpoint.getEndpoint(),
81+
NotificationEtagState.getInstance()
82+
)
83+
) {
7584
is UpdateCheckResult.HasUpdates -> {
7685
resourceResolver.get()
7786
.resolve(notificationsResource)

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationResourceResolver.kt

Lines changed: 0 additions & 127 deletions
This file was deleted.

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/ProcessNotificationsBase.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import software.aws.toolkits.core.utils.getLogger
1616
import software.aws.toolkits.core.utils.info
1717
import software.aws.toolkits.core.utils.inputStream
1818
import software.aws.toolkits.core.utils.warn
19+
import software.aws.toolkits.jetbrains.core.RemoteResourceResolverProvider
1920
import software.aws.toolkits.jetbrains.utils.notifyStickyWithData
2021
import java.util.concurrent.atomic.AtomicBoolean
2122

@@ -38,10 +39,10 @@ class ProcessNotificationsBase(
3839

3940
private fun getNotificationsFromFile(): NotificationsList? {
4041
try {
41-
val path = NotificationResourceResolverProvider
42+
val path = RemoteResourceResolverProvider
4243
.getInstance()
4344
.get()
44-
.getLocalResourcePath("notifications.json")
45+
.getLocalResourcePath(FILENAME)
4546
if (path == null) {
4647
LOG.warn { "Notifications file not found" }
4748
return null

plugins/core/jetbrains-community/tst/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingServiceTest.kt

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,29 @@ import org.junit.jupiter.api.AfterEach
1313
import org.junit.jupiter.api.BeforeEach
1414
import org.junit.jupiter.api.Test
1515
import org.junit.jupiter.api.extension.ExtendWith
16+
import software.aws.toolkits.core.utils.RemoteResourceResolver
17+
import software.aws.toolkits.core.utils.UpdateCheckResult
18+
import software.aws.toolkits.jetbrains.core.RemoteResourceResolverProvider
1619
import java.nio.file.Path
1720
import java.util.concurrent.CompletableFuture
1821

1922
@ExtendWith(ApplicationExtension::class)
2023
class NotificationPollingServiceTest {
2124
private lateinit var sut: NotificationPollingService
22-
private lateinit var mockResolver: NotificationResourceResolver
23-
private lateinit var mockProvider: NotificationResourceResolverProvider
25+
private lateinit var mockResolver: RemoteResourceResolver
26+
private lateinit var mockProvider: RemoteResourceResolverProvider
2427
private lateinit var observer: () -> Unit
2528
private val testPath = Path.of("/test/path")
2629

2730
@BeforeEach
2831
fun setUp() {
2932
sut = NotificationPollingService()
3033

31-
mockResolver = mockk<NotificationResourceResolver> {
34+
mockResolver = mockk<RemoteResourceResolver> {
3235
every { resolve(any()) } returns CompletableFuture.completedFuture(testPath)
3336
}
3437

35-
mockProvider = mockk<NotificationResourceResolverProvider> {
38+
mockProvider = mockk<RemoteResourceResolverProvider> {
3639
every { get() } returns mockResolver
3740
}
3841

@@ -59,21 +62,21 @@ class NotificationPollingServiceTest {
5962

6063
@Test
6164
fun `test pollForNotifications when ETag matches - no new notifications`() {
62-
every { mockResolver.checkForUpdates() } returns UpdateCheckResult.NoUpdates
65+
every { mockResolver.checkForUpdates(any(), any()) } returns UpdateCheckResult.NoUpdates
6366
sut.startPolling()
6467
verify(exactly = 0) { observer.invoke() }
6568
}
6669

6770
@Test
6871
fun `test pollForNotifications when ETag matches on startup - notify observers`() {
69-
every { mockResolver.checkForUpdates() } returns UpdateCheckResult.FirstPollCheck
72+
every { mockResolver.checkForUpdates(any(), any()) } returns UpdateCheckResult.FirstPollCheck
7073
sut.startPolling()
7174
verify(exactly = 1) { observer.invoke() }
7275
}
7376

7477
@Test
7578
fun `test pollForNotifications when ETag different - notify observers`() {
76-
every { mockResolver.checkForUpdates() } returns UpdateCheckResult.HasUpdates
79+
every { mockResolver.checkForUpdates(any(), any()) } returns UpdateCheckResult.HasUpdates
7780
sut.startPolling()
7881
verify(exactly = 1) { observer.invoke() }
7982
}

0 commit comments

Comments
 (0)