Skip to content

Commit 7501dfd

Browse files
authored
Merge pull request #2035 from digma-ai/feature/aggressive-update-notifications
force update Closes #2015
2 parents 8995a81 + 46f6b5e commit 7501dfd

File tree

45 files changed

+1605
-449
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1605
-449
lines changed

build.gradle.kts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,14 @@ dependencies {
7070
"configuration" to "riderDotNetObjects")))
7171
}
7272

73-
configurations {
74-
runtimeClasspath {
75-
//make sure we never package kotlin-stdlib-jdk8 or kotlin-stdlib-jdk7 because its is supplied by the IDE.
76-
//see more in
77-
//buildSrc/src/main/kotlin/digma-base.gradle.kts
78-
//settings.gradle.kts
79-
exclude("org.jetbrains.kotlin", "kotlin-stdlib-jdk8")
80-
exclude("org.jetbrains.kotlin", "kotlin-stdlib-jdk7")
81-
}
73+
configurations.getByName("runtimeClasspath") {
74+
//make sure we never package kotlin-stdlib-jdk8 or kotlin-stdlib-jdk7 because its is supplied by the IDE.
75+
//see more in
76+
//https://plugins.jetbrains.com/docs/intellij/using-kotlin.html#kotlin-standard-library
77+
//settings.gradle.kts
78+
exclude("org.jetbrains.kotlin", "kotlin-stdlib")
79+
exclude("org.jetbrains.kotlin", "kotlin-stdlib-jdk8")
80+
exclude("org.jetbrains.kotlin", "kotlin-stdlib-jdk7")
8281
}
8382

8483

@@ -144,7 +143,7 @@ project.afterEvaluate{
144143
tasks {
145144

146145
prepareSandbox{
147-
//copy rider dlls to the plugin sandbox so it is packaged in the zip
146+
//copy rider dlls to the plugin sandbox, so it is packaged in the zip
148147
from(configurations.getByName("riderDotNetObjects")){
149148
into("${properties("pluginName",project)}/dotnet/")
150149
}

ide-common/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ dependencies {
3030
api(libs.posthog)
3131
api(libs.maven.artifact)
3232
api(libs.glovoapp.versioning)
33+
api(libs.byte.buddy)
34+
3335

3436
implementation(project(":model"))
3537
implementation(project(":analytics-provider"))

ide-common/src/main/java/org/digma/intellij/plugin/analytics/AnalyticsService.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,15 +444,19 @@ public AssetNavigationResponse getAssetNavigation(@NotNull String spanCodeObject
444444
}
445445

446446
public InsightsStatsResult getInsightsStats(String spanCodeObjectId) throws AnalyticsServiceException {
447+
447448
try {
449+
var env = getCurrentEnvironment();
448450
var params = new HashMap<String, Object>();
449-
params.put("Environment",this.environment.getLatestKnownEnv());
451+
params.put("Environment", env);
450452

451453
if(spanCodeObjectId != null){
452454
params.put("ScopedSpanCodeObjectId", spanCodeObjectId);
453455
}
454456

455457
return executeCatching(() -> analyticsProviderProxy.getInsightsStats(params));
458+
} catch (NoSelectedEnvironmentException e) {
459+
Log.debugWithException(LOGGER, project, e, "error calling insights stats", e.getMessage());
456460
} catch (Exception e) {
457461
Log.warnWithException(LOGGER, project, e, "error calling insights stats", e.getMessage());
458462
}

ide-common/src/main/java/org/digma/intellij/plugin/analytics/Environment.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,6 @@ public Env getCurrent() {
4545
return current;
4646
}
4747

48-
@Override
49-
@NotNull
50-
public String getLatestKnownEnv() {
51-
return latestKnownEnv;
52-
}
53-
5448

5549
@Override
5650
public void setCurrent(@NotNull Env env) {

ide-common/src/main/java/org/digma/intellij/plugin/editor/EditorEventsHandler.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import org.digma.intellij.plugin.log.Log;
1414
import org.digma.intellij.plugin.model.discovery.*;
1515
import org.digma.intellij.plugin.psi.*;
16-
import org.digma.intellij.plugin.ui.MainToolWindowCardsController;
1716
import org.jetbrains.annotations.NotNull;
1817

1918
import static org.digma.intellij.plugin.common.AlarmUtilsKt.addRequestWithErrorReporting;
@@ -213,8 +212,6 @@ when editor with class A is opened and clicking another class ,say B, a caretPos
213212
caretListener.maybeAddCaretListener(selectedTextEditor);
214213
documentChangeListener.maybeAddDocumentListener(selectedTextEditor);
215214

216-
MainToolWindowCardsController.getInstance(project).showMainPanel();
217-
218215
int offset = selectedTextEditor.getCaretModel().getOffset();
219216

220217
Backgroundable.executeOnPooledThread(() -> {

ide-common/src/main/java/org/digma/intellij/plugin/ui/MainToolWindowCardsController.java

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.digma.intellij.plugin.ui;
22

33
import com.intellij.openapi.Disposable;
4+
import com.intellij.openapi.application.ApplicationManager;
45
import com.intellij.openapi.diagnostic.Logger;
56
import com.intellij.openapi.project.Project;
67
import com.intellij.openapi.wm.ToolWindow;
@@ -9,6 +10,7 @@
910
import org.digma.intellij.plugin.common.EDT;
1011
import org.digma.intellij.plugin.log.Log;
1112
import org.digma.intellij.plugin.ui.panels.DisposablePanel;
13+
import org.digma.intellij.plugin.updates.*;
1214
import org.jetbrains.annotations.NotNull;
1315

1416
import javax.swing.*;
@@ -30,8 +32,10 @@ public class MainToolWindowCardsController implements Disposable {
3032

3133
private static final Logger LOGGER = Logger.getInstance(MainToolWindowCardsController.class);
3234

35+
36+
3337
public enum MainWindowCard {
34-
MAIN, NO_CONNECTION
38+
MAIN, NO_CONNECTION, UPDATE_MODE
3539
}
3640

3741

@@ -45,6 +49,8 @@ public enum MainWindowCard {
4549
//the main card panel, our main view and no-connection panel
4650
private JPanel cardsPanel;
4751

52+
//never use latestCalledCard , only in initComponents
53+
private MainWindowCard latestCalledCard;
4854

4955
//wizard content is created and disposed when necessary. WizardComponents keeps the reference to the content and the panel.
5056
private final WizardComponents wizard = new WizardComponents();
@@ -62,9 +68,9 @@ public enum MainWindowCard {
6268
public MainToolWindowCardsController(@NotNull Project project) {
6369
this.project = project;
6470

65-
project.getMessageBus()
66-
.connect(this)
67-
.subscribe(AnalyticsServiceConnectionEvent.ANALYTICS_SERVICE_CONNECTION_EVENT_TOPIC, new AnalyticsServiceConnectionEvent() {
71+
ApplicationManager.getApplication().getMessageBus()
72+
.connect()
73+
.subscribe(BackendConnectionEvent.getBACKEND_CONNECTION_STATE_TOPIC(), new BackendConnectionEvent() {
6874
@Override
6975
public void connectionLost() {
7076
Log.log(LOGGER::debug, "Got connectionLost");
@@ -80,6 +86,10 @@ public void connectionGained() {
8086
}
8187
});
8288

89+
90+
ApplicationManager.getApplication().getMessageBus().connect().subscribe(AggressiveUpdateStateChangedEvent.Companion.getUPDATE_STATE_CHANGED_TOPIC(),
91+
(AggressiveUpdateStateChangedEvent) this::updateStateChanged);
92+
8393
}
8494

8595

@@ -125,9 +135,26 @@ public void initComponents(@NotNull ToolWindow toolWindow,
125135
if (isConnectionLost.get() || BackendConnectionMonitor.getInstance(project).isConnectionError()) {
126136
showNoConnection();
127137
}
138+
139+
//it may be that some showXXX is called before the components are initialized and
140+
// cardPanel was still null. one example is showUpdateBackendPanel that may be called very early.
141+
// so keep the latest called card and show it here after all components are initialized.
142+
if (latestCalledCard != null) {
143+
showCard(latestCalledCard);
144+
}
128145
}
129146

130147

148+
public void updateStateChanged(@NotNull PublicUpdateState updateState) {
149+
if (updateState.getUpdateState() == CurrentUpdateState.OK) {
150+
closeUpdateBackendPanel();
151+
} else {
152+
showUpdateBackendPanel();
153+
}
154+
}
155+
156+
157+
131158
public void showWizard(Boolean wizardSkipInstallationStep) {
132159
Log.log(LOGGER::debug, "showWizard called");
133160

@@ -311,7 +338,40 @@ public void showMainPanel() {
311338
Log.log(LOGGER::debug, "Not showing MainPanel because connection lost, showing NoConnection");
312339
showNoConnection();
313340
} else {
314-
//FileEditorManager must be called on EDT
341+
342+
EDT.ensureEDT(() -> showCard(MainWindowCard.MAIN));
343+
}
344+
}
345+
346+
private void showUpdateBackendPanel() {
347+
348+
Log.log(LOGGER::debug, "showUpdateBackendPanel called");
349+
350+
//replace the card even if wizard is on. it will not show until wizard content is removed.
351+
352+
//this may happen on startup,showMainPanel is called from the tool window factory,
353+
// but there may be a connection lost before the content was built and before this controller was initialized
354+
if (isConnectionLost.get()) {
355+
Log.log(LOGGER::debug, "Not showing MainPanel because connection lost, showing NoConnection");
356+
showNoConnection();
357+
} else {
358+
EDT.ensureEDT(() -> showCard(MainWindowCard.UPDATE_MODE));
359+
}
360+
}
361+
362+
private void closeUpdateBackendPanel() {
363+
364+
Log.log(LOGGER::debug, "closeUpdateBackendPanel called");
365+
366+
367+
//replace the card even if wizard is on. it will not show until wizard content is removed.
368+
369+
//this may happen on startup,showMainPanel is called from the tool window factory,
370+
// but there may be a connection lost before the content was built and before this controller was initialized
371+
if (isConnectionLost.get()) {
372+
Log.log(LOGGER::debug, "Not showing MainPanel because connection lost, showing NoConnection");
373+
showNoConnection();
374+
} else {
315375
EDT.ensureEDT(() -> showCard(MainWindowCard.MAIN));
316376
}
317377
}
@@ -328,11 +388,25 @@ private void showNoConnection() {
328388

329389
private void showCard(MainWindowCard card) {
330390
Log.log(LOGGER::debug, "showCard called with {}", card);
391+
392+
//need to keep the UPDATE_MODE if AggressiveUpdateService is still in update mode.
393+
// after AggressiveUpdateService enters update mode there may be connection lost, the connectionLost
394+
// will change to NO_CONNECTION, in that case we want to see the no connection message.
395+
// on connectionGained the listener will try to change it to MAIN but if
396+
// AggressiveUpdateService is still in update mode we need to replace back to UPDATE_MODE
397+
MainWindowCard cardToUse;
398+
if (AggressiveUpdateService.getInstance().isInUpdateMode() && card == MainWindowCard.MAIN) {
399+
cardToUse = MainWindowCard.UPDATE_MODE;
400+
} else {
401+
cardToUse = card;
402+
}
403+
404+
latestCalledCard = card;
331405
if (cardsPanel == null) {
332406
Log.log(LOGGER::debug, project, "show {} was called but cardsPanel is null", card);
333407
} else {
334408
Log.log(LOGGER::debug, project, "Showing card {}", card);
335-
EDT.ensureEDT(() -> ((CardLayout) cardsPanel.getLayout()).show(cardsPanel, card.name()));
409+
EDT.ensureEDT(() -> ((CardLayout) cardsPanel.getLayout()).show(cardsPanel, cardToUse.name()));
336410
}
337411
}
338412

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package org.digma.intellij.plugin.analytics
2+
3+
import com.intellij.util.messages.Topic
4+
5+
6+
/**
7+
* this is an application event for connection state.
8+
* AnalyticsServiceConnectionEvent is a project event, but it actually should be
9+
* application event because the backend is one for all projects.
10+
*/
11+
//todo: replace AnalyticsServiceConnectionEvent with this event
12+
interface BackendConnectionEvent {
13+
companion object {
14+
@JvmStatic
15+
@Topic.AppLevel
16+
val BACKEND_CONNECTION_STATE_TOPIC: Topic<BackendConnectionEvent> = Topic.create(
17+
"BACKEND CONNECTION STATE CHANGED",
18+
BackendConnectionEvent::class.java
19+
)
20+
}
21+
22+
fun connectionLost()
23+
24+
fun connectionGained()
25+
26+
27+
}

ide-common/src/main/kotlin/org/digma/intellij/plugin/analytics/BackendConnectionMonitor.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.digma.intellij.plugin.analytics
22

33
import com.intellij.openapi.Disposable
4+
import com.intellij.openapi.application.ApplicationManager
45
import com.intellij.openapi.components.Service
56
import com.intellij.openapi.project.Project
67
import com.intellij.util.messages.MessageBusConnection
@@ -55,10 +56,14 @@ class BackendConnectionMonitor(val project: Project) : Disposable, AnalyticsServ
5556

5657
override fun connectionLost() {
5758
connectionError()
59+
//using this event as a bridge to fire BackendConnectionEvent
60+
ApplicationManager.getApplication().messageBus.syncPublisher(BackendConnectionEvent.BACKEND_CONNECTION_STATE_TOPIC).connectionLost()
5861
}
5962

6063
override fun connectionGained() {
6164
connectionOk()
65+
//using this event as a bridge to fire BackendConnectionEvent
66+
ApplicationManager.getApplication().messageBus.syncPublisher(BackendConnectionEvent.BACKEND_CONNECTION_STATE_TOPIC).connectionGained()
6267
}
6368

6469
}

ide-common/src/main/kotlin/org/digma/intellij/plugin/common/ProjectUtils.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,22 @@ import com.intellij.openapi.wm.IdeFocusManager
77

88
fun findActiveProject(): Project? {
99

10-
//best effort to find a project for the notification
10+
//best effort to find aa active project
1111

1212
var project = ProjectUtil.getActiveProject()
13-
if (project == null || project.isDisposed) {
13+
if (project == null || !isProjectValid(project)) {
1414
project = IdeFocusManager.getGlobalInstance().lastFocusedFrame?.project
1515
}
1616

17-
if (project == null || project.isDisposed) {
17+
if (project == null || !isProjectValid(project)) {
1818
project = ProjectManager.getInstance().openProjects.firstOrNull { p -> !p.isDisposed }
1919
}
2020

21-
return project
21+
return project?.takeIf { isProjectValid(project) }
2222

2323
}
2424

2525

2626
fun isProjectValid(project: Project): Boolean {
27-
return !project.isDisposed && !project.isDefault
27+
return !project.isDisposed && !project.isDefault && project.isOpen
2828
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package org.digma.intellij.plugin.common
2+
3+
import com.intellij.openapi.application.ApplicationInfo
4+
import org.digma.intellij.plugin.model.rest.version.VersionRequest
5+
import org.digma.intellij.plugin.semanticversion.SemanticVersionUtil
6+
7+
8+
// returns one of:
9+
// IC - Intellij Community
10+
// RD - Rider
11+
fun getPlatformType(): String {
12+
val appInfo = ApplicationInfo.getInstance()
13+
return appInfo.build.productCode
14+
}
15+
16+
fun getPlatformVersion(): String {
17+
val appInfo = ApplicationInfo.getInstance()
18+
return appInfo.fullVersion
19+
}
20+
21+
// when plugin is not installed it will return 0.0.0
22+
fun getPluginVersion(defaultIfNotFound: String = "0.0.0"): String {
23+
return SemanticVersionUtil.getPluginVersionWithoutBuildNumberAndPreRelease(defaultIfNotFound)
24+
}
25+
26+
27+
fun buildVersionRequest(): VersionRequest {
28+
return VersionRequest(
29+
getPluginVersion(), getPlatformType(), getPlatformVersion()
30+
)
31+
}

0 commit comments

Comments
 (0)