Skip to content

Commit 81a425e

Browse files
authored
CM-29952 - Fix creation of many scan jobs on many on-save events for a short period of time (#31)
1 parent 5d567d3 commit 81a425e

File tree

6 files changed

+64
-18
lines changed

6 files changed

+64
-18
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@
44

55
## [Unreleased]
66

7+
## [1.0.1] - 2023-12-12
8+
9+
Fix the creation of many scan jobs on many on-save events for a short period of time.
10+
711
## [1.0.0] - 2023-12-05
812

913
The first public release of the plugin.
1014

15+
[1.0.1]: https://github.com/cycodehq/intellij-platform-plugin/releases/tag/v1.0.1
1116
[1.0.0]: https://github.com/cycodehq/intellij-platform-plugin/releases/tag/v1.0.0
1217
[Unreleased]: https://github.com/cycodehq/intellij-platform-plugin/compare/v1.0.0...HEAD

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pluginGroup = com.cycode.plugin
44
pluginName = Cycode (beta)
55
pluginRepositoryUrl = https://github.com/cycodehq/intellij-platform-plugin
66
# SemVer format -> https://semver.org
7-
pluginVersion = 1.0.0
7+
pluginVersion = 1.0.1
88

99
# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
1010
pluginSinceBuild = 211.1

src/main/kotlin/com/cycode/plugin/Consts.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ class Consts {
99
val DEFAULT_CLI_PATH = "$PLUGIN_PATH/cycode" + if (SystemInfo.isWindows) ".exe" else ""
1010
const val CLI_GITHUB_ORG = "cycodehq"
1111
const val CLI_GITHUB_REPO = "cycode-cli"
12-
const val CLI_GITHUB_TAG = "v1.5.0"
12+
const val CLI_GITHUB_TAG = "v1.6.0"
1313
const val CLI_CHECK_NEW_VERSION_EVERY_SEC = 24 * 60 * 60 // 24 hours
14+
const val PLUGIN_AUTO_SAVE_FLUSH_INITIAL_DELAY_SEC = 0L
15+
const val PLUGIN_AUTO_SAVE_FLUSH_DELAY_SEC = 5L
1416
}
1517
}
Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.cycode.plugin.listeners
22

3+
import com.cycode.plugin.Consts
34
import com.cycode.plugin.CycodeBundle
45
import com.cycode.plugin.services.cli
56
import com.cycode.plugin.services.pluginSettings
@@ -11,31 +12,65 @@ import com.intellij.openapi.fileEditor.FileDocumentManagerListener
1112
import com.intellij.openapi.progress.ProgressIndicator
1213
import com.intellij.openapi.progress.Task
1314
import com.intellij.openapi.project.Project
15+
import com.intellij.util.concurrency.AppExecutorUtil
16+
import java.io.File
17+
import java.util.concurrent.TimeUnit
1418

1519

1620
class FileSaveListener(private val project: Project) : FileDocumentManagerListener {
1721
private val cliService = cli(project)
1822
private val pluginState = pluginState()
1923
private val pluginSettings = pluginSettings()
24+
private val collectedPathsToScan = mutableSetOf<String>() // we use a set to avoid duplicates
2025

21-
override fun beforeDocumentSaving(document: Document) {
22-
thisLogger().debug("FileSaveListener.beforeDocumentSaving")
26+
init {
27+
scheduleScanPathsFlush()
28+
}
2329

24-
if (!pluginSettings.scanOnSave || !pluginState.cliAuthed) {
30+
private fun scanPathsFlush() {
31+
val pathsToScan = excludeNotExistingPaths(collectedPathsToScan.toMutableList())
32+
collectedPathsToScan.clear()
33+
34+
if (pathsToScan.isEmpty() || !pluginState.cliAuthed) {
2535
return
2636
}
2737

28-
val file = FileDocumentManager.getInstance().getFile(document) ?: return
29-
val filePath = file.canonicalFile?.canonicalPath ?: return
30-
3138
object : Task.Backgroundable(project, CycodeBundle.message("fileScanning"), true) {
3239
override fun run(indicator: ProgressIndicator) {
3340
cliService.cliShouldDestroyCallback = { indicator.isCanceled }
3441

35-
thisLogger().debug("Start scanning file: $filePath")
36-
cliService.scanFileSecrets(filePath, false)
37-
thisLogger().debug("Finish scanning file: $filePath")
42+
thisLogger().debug("Start scanning paths: $pathsToScan")
43+
cliService.scanPathsSecrets(pathsToScan, false)
44+
thisLogger().debug("Finish scanning paths: $pathsToScan")
3845
}
3946
}.queue()
4047
}
48+
49+
private fun excludeNotExistingPaths(paths: List<String>): List<String> {
50+
return paths.filter { File(it).exists() }
51+
}
52+
53+
private fun scheduleScanPathsFlush() {
54+
AppExecutorUtil.getAppScheduledExecutorService().scheduleWithFixedDelay(
55+
{
56+
scanPathsFlush()
57+
},
58+
Consts.PLUGIN_AUTO_SAVE_FLUSH_INITIAL_DELAY_SEC,
59+
Consts.PLUGIN_AUTO_SAVE_FLUSH_DELAY_SEC,
60+
TimeUnit.SECONDS
61+
)
62+
}
63+
64+
override fun beforeDocumentSaving(document: Document) {
65+
thisLogger().debug("FileSaveListener.beforeDocumentSaving")
66+
67+
if (!pluginSettings.scanOnSave || !pluginState.cliAuthed) {
68+
return
69+
}
70+
71+
val file = FileDocumentManager.getInstance().getFile(document) ?: return
72+
val filePath = file.canonicalFile?.canonicalPath ?: return
73+
74+
collectedPathsToScan.add(filePath)
75+
}
4176
}

src/main/kotlin/com/cycode/plugin/services/CliService.kt

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,25 +147,29 @@ class CliService(private val project: Project) {
147147
}
148148
}
149149

150-
private inline fun <reified T> scanFile(filePath: String, scanType: CliScanType): CliResult<T>? {
150+
private inline fun <reified T> scanPaths(paths: List<String>, scanType: CliScanType): CliResult<T>? {
151151
val scanTypeString = scanType.name.toLowerCase()
152152
val result = cli
153153
.executeCommand<T>(
154154
"scan",
155155
"-t",
156156
scanTypeString,
157157
"path",
158-
filePath,
158+
*getPathsAsArguments(paths),
159159
shouldDestroyCallback = cliShouldDestroyCallback
160160
)
161161

162162
return processResult(result)
163163
}
164164

165-
fun scanFileSecrets(filePath: String, onDemand: Boolean = true) {
166-
val results = scanFile<SecretScanResult>(filePath, CliScanType.Secret)
165+
private fun getPathsAsArguments(paths: List<String>): Array<String> {
166+
return paths.toTypedArray()
167+
}
168+
169+
fun scanPathsSecrets(paths: List<String>, onDemand: Boolean = true) {
170+
val results = scanPaths<SecretScanResult>(paths, CliScanType.Secret)
167171
if (results == null) {
168-
thisLogger().warn("Failed to scan file: $filePath")
172+
thisLogger().warn("Failed to scan paths: $paths")
169173
return
170174
}
171175

src/main/kotlin/com/cycode/plugin/services/CycodeService.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class CycodeService(val project: Project) {
6767
}
6868

6969
cliService.cliShouldDestroyCallback = { indicator.isCanceled }
70-
cliService.scanFileSecrets(filepath)
70+
cliService.scanPathsSecrets(listOf(filepath))
7171
}
7272
}.queue()
7373
}
@@ -87,7 +87,7 @@ class CycodeService(val project: Project) {
8787
// the right way: apply "ignore rules" in the local results db of the plugin
8888
// the disadvantage of the right way: we rewrite code that already exists in CLI in every plugin...
8989
// TODO(MarshalX): think about what we can do from CLI side
90-
cliService.scanFileSecrets(filepath)
90+
cliService.scanPathsSecrets(listOf(filepath))
9191
}
9292
}.queue()
9393
}

0 commit comments

Comments
 (0)