You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ma...@apache.org on 2023/05/15 18:59:13 UTC

[camel-karavan] branch main updated: Reload and log scroll #757

This is an automated email from the ASF dual-hosted git repository.

marat pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-karavan.git


The following commit(s) were added to refs/heads/main by this push:
     new 75cda858 Reload and log scroll #757
75cda858 is described below

commit 75cda85822585787cc4477c106016d8832ace99a
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Mon May 15 14:59:03 2023 -0400

    Reload and log scroll #757
---
 .../org/apache/camel/karavan/api/RunnerResource.java   | 15 ++++++++-------
 .../camel/karavan/service/InfinispanService.java       |  8 ++++++++
 .../camel/karavan/service/KubernetesService.java       |  3 +--
 .../apache/camel/karavan/service/RunnerService.java    | 18 ++++++++----------
 karavan-app/src/main/webui/src/projects/ProjectLog.tsx | 16 +++++++++++++---
 5 files changed, 38 insertions(+), 22 deletions(-)

diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/api/RunnerResource.java b/karavan-app/src/main/java/org/apache/camel/karavan/api/RunnerResource.java
index eb169a48..6e506794 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/api/RunnerResource.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/api/RunnerResource.java
@@ -16,7 +16,6 @@
  */
 package org.apache.camel.karavan.api;
 
-import io.vertx.core.json.JsonObject;
 import org.apache.camel.karavan.model.PodStatus;
 import org.apache.camel.karavan.model.Project;
 import org.apache.camel.karavan.model.RunnerStatus;
@@ -38,6 +37,7 @@ import javax.ws.rs.core.Response;
 import java.util.Optional;
 
 import static org.apache.camel.karavan.service.RunnerService.RUNNER_SUFFIX;
+import static org.apache.camel.karavan.service.RunnerService.STATUS_NEED_INITIAL_LOAD;
 
 @Path("/api/runner")
 public class RunnerResource {
@@ -57,21 +57,22 @@ public class RunnerResource {
     @POST
     @Produces(MediaType.APPLICATION_JSON)
     @Consumes(MediaType.APPLICATION_JSON)
-    public String runProject(Project project) {
+    public Response runProject(Project project) {
         String runnerName = project.getProjectId() + "-" + RUNNER_SUFFIX;
         String status = infinispanService.getRunnerStatus(runnerName, RunnerStatus.NAME.context);
-        if (status != null) {
-            JsonObject js = new JsonObject(status);
+        if (status == null) {
+            Project p = infinispanService.getProject(project.getProjectId());
+            infinispanService.saveRunnerStatus(runnerName, STATUS_NEED_INITIAL_LOAD, STATUS_NEED_INITIAL_LOAD);
+            return Response.ok(kubernetesService.tryCreateRunner(p, runnerName)).build();
         }
-        Project p = infinispanService.getProject(project.getProjectId());
-        return kubernetesService.tryCreateRunner(p, runnerName);
+        return Response.notModified().build();
     }
 
     @GET
     @Produces(MediaType.APPLICATION_JSON)
     @Path("/reload/{projectId}")
     public Response reload(@PathParam("projectId") String projectId) {
-        runnerServices.reload(projectId);
+        runnerServices.reloadProjectCode(projectId);
         return Response.ok().build();
     }
 
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/service/InfinispanService.java b/karavan-app/src/main/java/org/apache/camel/karavan/service/InfinispanService.java
index b09a0831..6d3072ee 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/service/InfinispanService.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/service/InfinispanService.java
@@ -331,10 +331,18 @@ public class InfinispanService implements HealthCheck  {
         runnerStatuses.put(GroupedKey.create(podName, statusName.name()), status);
     }
 
+    public void saveRunnerStatus(String podName, String statusName, String status) {
+        runnerStatuses.put(GroupedKey.create(podName, statusName), status);
+    }
+
     public void deleteRunnerStatus(String podName, RunnerStatus.NAME statusName) {
         runnerStatuses.remove(GroupedKey.create(podName, statusName.name()));
     }
 
+    public void deleteRunnerStatus(String podName, String statusName) {
+        runnerStatuses.remove(GroupedKey.create(podName, statusName));
+    }
+
     public void deleteRunnerStatuses(String podName) {
         Arrays.stream(RunnerStatus.NAME.values()).forEach(statusName -> {
             runnerStatuses.remove(GroupedKey.create(podName, statusName.name()));
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/service/KubernetesService.java b/karavan-app/src/main/java/org/apache/camel/karavan/service/KubernetesService.java
index 0224e4e4..02ae8f03 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/service/KubernetesService.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/service/KubernetesService.java
@@ -382,7 +382,6 @@ public class KubernetesService implements HealthCheck{
     }
 
     public String tryCreateRunner(Project project, String runnerName) {
-
         createPVC(runnerName);
         Pod old = kubernetesClient().pods().inNamespace(getNamespace()).withName(runnerName).get();
         if (old == null) {
@@ -390,7 +389,7 @@ public class KubernetesService implements HealthCheck{
             Map<String,String> containerResources = ServiceUtil
                     .getRunnerContainerResourcesMap(properties, isOpenshift(), project.getRuntime().equals("quarkus"));
             Pod pod = getPod(project.getProjectId(), runnerName, containerResources);
-            Pod result = kubernetesClient().resource(pod).create();
+            Pod result = kubernetesClient().resource(pod).createOrReplace();
             LOGGER.info("Created pod " + result.getMetadata().getName());
         }
         createService(runnerName);
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/service/RunnerService.java b/karavan-app/src/main/java/org/apache/camel/karavan/service/RunnerService.java
index 380bc94e..22b31af8 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/service/RunnerService.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/service/RunnerService.java
@@ -42,6 +42,7 @@ public class RunnerService {
     private static final Logger LOGGER = Logger.getLogger(RunnerService.class.getName());
     public static final String CMD_COLLECT_RUNNER_STATUS = "collect-runner-status";
     public static final String RUNNER_SUFFIX = "runner";
+    public static final String STATUS_NEED_INITIAL_LOAD = "NEED_INITIAL_LOAD";
 
     @Inject
     InfinispanService infinispanService;
@@ -67,14 +68,16 @@ public class RunnerService {
         return webClient;
     }
 
-    public void reload(String projectId) {
+    public void reloadProjectCode(String projectId) {
+        LOGGER.info("Reload project code " + projectId);
+        String runnerName = projectId + "-" + RUNNER_SUFFIX;
         try {
-            String runnerName = projectId + "-" + RUNNER_SUFFIX;
             infinispanService.getProjectFiles(projectId).forEach(projectFile -> putRequest(runnerName, projectFile.getName(), projectFile.getCode(), 1000));
             reloadRequest(runnerName);
         } catch (Exception ex) {
             LOGGER.error(ex.getMessage());
         }
+        infinispanService.deleteRunnerStatus(runnerName, STATUS_NEED_INITIAL_LOAD);
     }
 
     @CircuitBreaker(requestVolumeThreshold = 10, failureRatio = 0.5, delay = 1000)
@@ -114,6 +117,7 @@ public class RunnerService {
         String oldContext = infinispanService.getRunnerStatus(podName, RunnerStatus.NAME.context);
         String newContext = getRunnerStatus(podName, RunnerStatus.NAME.context);
         if (newContext != null) {
+            System.out.println(new JsonObject(newContext).encodePrettily());
             infinispanService.saveRunnerStatus(podName, RunnerStatus.NAME.context, newContext);
             Arrays.stream(RunnerStatus.NAME.values())
                     .filter(name -> !name.equals(RunnerStatus.NAME.context))
@@ -131,17 +135,11 @@ public class RunnerService {
         String projectName = podName.replace("-" + RUNNER_SUFFIX, "");
         String newState = getContextState(newContext);
         String oldState = getContextState(oldContext);
-        if (newContext != null && !Objects.equals(newState, oldState) && "Running".equals(newState)) {
-            sendCodeToRunner(projectName);
+        if (newContext != null && !Objects.equals(newState, oldState) && "Started".equals(newState)) {
+            reloadProjectCode(projectName);
         }
     }
 
-    private void sendCodeToRunner(String projectName) {
-        infinispanService.getProjectFiles(projectName).forEach(projectFile -> {
-
-        });
-    }
-
     private String getContextState(String context) {
         if (context != null) {
             JsonObject obj = new JsonObject(context);
diff --git a/karavan-app/src/main/webui/src/projects/ProjectLog.tsx b/karavan-app/src/main/webui/src/projects/ProjectLog.tsx
index 829c58c7..3bfacd36 100644
--- a/karavan-app/src/main/webui/src/projects/ProjectLog.tsx
+++ b/karavan-app/src/main/webui/src/projects/ProjectLog.tsx
@@ -5,6 +5,7 @@ import CloseIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';
 import ExpandIcon from '@patternfly/react-icons/dist/esm/icons/expand-icon';
 import ScrollIcon from '@patternfly/react-icons/dist/esm/icons/scroll-icon';
 import CollapseIcon from '@patternfly/react-icons/dist/esm/icons/compress-icon';
+import CleanIcon from '@patternfly/react-icons/dist/esm/icons/trash-alt-icon';
 import {LogViewer} from '@patternfly/react-log-viewer';
 import {Subscription} from "rxjs";
 import {ProjectEventBus, ShowLogCommand} from "./ProjectEventBus";
@@ -21,6 +22,7 @@ interface State {
     height?: number | string,
     logViewerRef: any,
     isTextWrapped: boolean
+    autoScroll: boolean
     data: string,
     currentLine: number
 }
@@ -32,6 +34,7 @@ export class ProjectLog extends React.Component<Props, State> {
         height: INITIAL_LOG_HEIGHT,
         logViewerRef: React.createRef(),
         isTextWrapped: true,
+        autoScroll: true,
         data: '',
         currentLine: 0
     }
@@ -66,15 +69,23 @@ export class ProjectLog extends React.Component<Props, State> {
                 const data = state.data.concat('\n').concat(event.data)
                 return {data: data, currentLine: this.state.currentLine + 1}
             });
+            if (this.state.autoScroll) {
+                this.state.logViewerRef.current.scrollToBottom();
+            }
         };
     }
 
     getButtons() {
-        const {height, isTextWrapped, logViewerRef, log, data} = this.state;
+        const {height, isTextWrapped, logViewerRef, log, data, autoScroll} = this.state;
         return (<div className="buttons">
             <Label className="log-name">{log?.type + ": " + log?.name}</Label>
+            <Tooltip content={"Clean log"} position={TooltipPosition.bottom}>
+                <Button variant="plain" onClick={() => this.setState({data: ''})} icon={<CleanIcon/>}/>
+            </Tooltip>
             <Checkbox label="Wrap text" aria-label="wrap text checkbox" isChecked={isTextWrapped} id="wrap-text-checkbox"
                       onChange={checked => this.setState({isTextWrapped: checked})} />
+            <Checkbox label="Autoscroll" aria-label="autoscroll checkbox" isChecked={autoScroll} id="autoscroll-checkbox"
+                      onChange={checked => this.setState({autoScroll: checked})} />
             <Tooltip content={"Scroll to bottom"} position={TooltipPosition.bottom}>
                 <Button variant="plain" onClick={() => logViewerRef.current.scrollToBottom()} icon={<ScrollIcon/>}/>
             </Tooltip>
@@ -103,8 +114,7 @@ export class ProjectLog extends React.Component<Props, State> {
                     header={this.getButtons()}
                     height={"100vh"}
                     data={data}
-                    scrollToRow={currentLine}
-                    overScanCount={10}
+                    // scrollToRow={currentLine}
                     theme={'dark'}/>
             </PageSection>
             : <></>);