From 713f3dd74c54ba96e6351d5b608c9528ad797066 Mon Sep 17 00:00:00 2001 From: Kavith Lokuhewage Date: Fri, 8 Nov 2019 22:51:02 +0530 Subject: [PATCH 1/8] Refactor PersistantVolume & claims --- k8s/compiler/compiler-deployment.yaml | 2 +- k8s/executor/executor-deployment.yaml | 2 +- k8s/kubectl-set-namespace.sh | 2 ++ k8s/nfs/pv-and-pvc.yaml | 13 ++++++------- k8s/undeploy-nfs.sh | 4 ++-- 5 files changed, 12 insertions(+), 11 deletions(-) create mode 100755 k8s/kubectl-set-namespace.sh diff --git a/k8s/compiler/compiler-deployment.yaml b/k8s/compiler/compiler-deployment.yaml index 291c24c..024a2b9 100644 --- a/k8s/compiler/compiler-deployment.yaml +++ b/k8s/compiler/compiler-deployment.yaml @@ -23,7 +23,7 @@ spec: volumes: - name: pvc-nfs persistentVolumeClaim: - claimName: nfs + claimName: pvc-build-cache-rw containers: - name: ballerina-playground-compiler-container imagePullPolicy: Always diff --git a/k8s/executor/executor-deployment.yaml b/k8s/executor/executor-deployment.yaml index b663290..93e1fbd 100644 --- a/k8s/executor/executor-deployment.yaml +++ b/k8s/executor/executor-deployment.yaml @@ -23,7 +23,7 @@ spec: volumes: - name: pvc-nfs persistentVolumeClaim: - claimName: nfs + claimName: pvc-build-cache-rw containers: - name: ballerina-playground-executor-container imagePullPolicy: Always diff --git a/k8s/kubectl-set-namespace.sh b/k8s/kubectl-set-namespace.sh new file mode 100755 index 0000000..7467d10 --- /dev/null +++ b/k8s/kubectl-set-namespace.sh @@ -0,0 +1,2 @@ +#!/bin/bash +kubectl config set-context --current --namespace=ballerina-playground-v2 \ No newline at end of file diff --git a/k8s/nfs/pv-and-pvc.yaml b/k8s/nfs/pv-and-pvc.yaml index b4bf60b..9e4bb41 100644 --- a/k8s/nfs/pv-and-pvc.yaml +++ b/k8s/nfs/pv-and-pvc.yaml @@ -1,27 +1,26 @@ apiVersion: v1 kind: PersistentVolume metadata: - name: nfs - annotations: - pv.beta.kubernetes.io/gid: "1000" + name: pv-build-cache spec: + storageClassName: build.cache capacity: storage: 100Gi accessModes: - ReadWriteMany nfs: server: nfs-server.${BPG_NAMESPACE}.svc.cluster.local - path: "/exports" + path: "/exports/cache_101" --- kind: PersistentVolumeClaim apiVersion: v1 metadata: - name: nfs + name: pvc-build-cache-rw spec: accessModes: - ReadWriteMany - storageClassName: "" + storageClassName: build.cache resources: requests: - storage: 90Gi \ No newline at end of file + storage: 100Gi \ No newline at end of file diff --git a/k8s/undeploy-nfs.sh b/k8s/undeploy-nfs.sh index b47cc7a..e860085 100755 --- a/k8s/undeploy-nfs.sh +++ b/k8s/undeploy-nfs.sh @@ -1,4 +1,4 @@ kubectl delete svc nfs-server -n ballerina-playground-v2 kubectl delete deployment nfs-server -n ballerina-playground-v2 -kubectl delete pvc nfs -n ballerina-playground-v2 -kubectl delete pv nfs -n ballerina-playground-v2 +kubectl delete pvc pvc-build-cache-rw -n ballerina-playground-v2 +kubectl delete pv pv-build-cache -n ballerina-playground-v2 From cd9cd396a2a4111dccfa3d60702949f3b0130591 Mon Sep 17 00:00:00 2001 From: Kavith Lokuhewage Date: Sat, 9 Nov 2019 05:45:05 +0530 Subject: [PATCH 2/8] Prevent parallel runs per client --- web/src/components/Playground.tsx | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/web/src/components/Playground.tsx b/web/src/components/Playground.tsx index 35e214b..d3dc3d5 100644 --- a/web/src/components/Playground.tsx +++ b/web/src/components/Playground.tsx @@ -78,12 +78,17 @@ export class Playground extends React.Component<{}, IPlaygroundState> { } private onRun() { + const { session, sourceCode, runInProgress } = this.state; + // prevent parallel runs per client + if (runInProgress) { + return; + } // clear console and set waiting on remote server. this.setState({ responses: [], + runInProgress: true, waitingOnRemoteServer: true, }); - const { session, sourceCode } = this.state; if (session) { if (!session.isOpen()) { this.createConnection(); @@ -94,8 +99,16 @@ export class Playground extends React.Component<{}, IPlaygroundState> { private onResponse(resp: PlaygroundResponse) { const { responses } = this.state; + let runInProgress = true; + const { type, data } = resp; + if (type === "Control" + && (data === "Finished Executing." || data === "Finished Compiling with errors.") + ) { + runInProgress = false; + } this.setState({ responses: [...responses, resp], + runInProgress, waitingOnRemoteServer: false, }); } @@ -138,6 +151,7 @@ export class Playground extends React.Component<{}, IPlaygroundState> { const { responses } = this.state; this.setState({ responses: [...responses, { type: "Error", data: msg }], + runInProgress: false, }); } } From 9223ed54d91e31aea097d334313f240a237f3330 Mon Sep 17 00:00:00 2001 From: Kavith Lokuhewage Date: Sat, 9 Nov 2019 06:17:07 +0530 Subject: [PATCH 3/8] Always display only the last control msg --- web/src/components/OutputPanel.tsx | 51 ++++++++++++++++++------------ 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/web/src/components/OutputPanel.tsx b/web/src/components/OutputPanel.tsx index 5300919..a7e276e 100644 --- a/web/src/components/OutputPanel.tsx +++ b/web/src/components/OutputPanel.tsx @@ -2,33 +2,42 @@ import * as React from "react"; import "./OutputPanel.less"; import { PlaygroundContext } from "./Playground"; +export function createHTMLFormattedText(text: string) { + return text.split(/\n/g).map((val) => { + const tabbedPieces = val.split(/\t/g); + return ( +
+ { + tabbedPieces.length === 1 && {val} + } + { + tabbedPieces.length > 1 && + tabbedPieces + .map((tabbedSegment) => +     {tabbedSegment}, + ) + } +
+ ); + }); +} + export function OutputPanel() { return {({ responses, waitingOnRemoteServer }) => (
{waitingOnRemoteServer &&
Waiting on remote server
} { - responses.map(({ type, data }) => ( -
- {data.split(/\n/g).map((val) => { - const tabbedPieces = val.split(/\t/g); - return ( -
- { - tabbedPieces.length === 1 && {val} - } - { - tabbedPieces.length > 1 && - val.split(/\t/g) - .map((tabbedSegment) => -     {tabbedSegment}, - ) - } -
- ); - })} -
- )) + responses.map(({ type, data }, index) => { + if (type === "Control" && (index !== responses.length - 1)) { + return ; + } + return ( +
+ {createHTMLFormattedText(data)} +
+ ); + }) }
)} From df43916ebf7fe757b84887e73c7b9947669d38de Mon Sep 17 00:00:00 2001 From: Kavith Lokuhewage Date: Sat, 9 Nov 2019 07:27:19 +0530 Subject: [PATCH 4/8] Add ballerina logo & favicons --- web/images/android-chrome-192x192.png | Bin 0 -> 3184 bytes web/images/android-chrome-512x512.png | Bin 0 -> 8776 bytes web/images/apple-touch-icon.png | Bin 0 -> 3049 bytes web/images/ballerina-logo-play.svg | 15 +++++ web/images/ballerina-logo.svg | 52 +++++++++++++++ web/images/browserconfig.xml | 9 +++ web/images/favicon-16x16.png | Bin 0 -> 563 bytes web/images/favicon-32x32.png | Bin 0 -> 808 bytes web/images/favicon.ico | Bin 0 -> 15086 bytes web/images/mstile-150x150.png | Bin 0 -> 2335 bytes web/images/safari-pinned-tab.svg | 89 ++++++++++++++++++++++++++ web/images/site.webmanifest | 19 ++++++ web/src/components/ControlPanel.less | 5 ++ web/src/components/ControlPanel.tsx | 2 + web/src/components/OutputPanel.tsx | 5 +- web/src/index.ejs | 7 ++ web/webpack.config.js | 3 +- 17 files changed, 204 insertions(+), 2 deletions(-) create mode 100644 web/images/android-chrome-192x192.png create mode 100644 web/images/android-chrome-512x512.png create mode 100644 web/images/apple-touch-icon.png create mode 100644 web/images/ballerina-logo-play.svg create mode 100644 web/images/ballerina-logo.svg create mode 100644 web/images/browserconfig.xml create mode 100644 web/images/favicon-16x16.png create mode 100644 web/images/favicon-32x32.png create mode 100644 web/images/favicon.ico create mode 100644 web/images/mstile-150x150.png create mode 100644 web/images/safari-pinned-tab.svg create mode 100644 web/images/site.webmanifest diff --git a/web/images/android-chrome-192x192.png b/web/images/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..40ba71c70f1dbba726b007352ae7fa3f6e8fbc1a GIT binary patch literal 3184 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 p2_IgV8R#47kNH~V@?_{1r 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 literal 0 HcmV?d00001 diff --git a/web/images/apple-touch-icon.png b/web/images/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..bcbd0c151a08fbd9e347ed3bcecbe59ba79d2ed7 GIT binary patch literal 3049 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 + + + + + + + + + + + diff --git a/web/images/ballerina-logo.svg b/web/images/ballerina-logo.svg new file mode 100644 index 0000000..b09b249 --- /dev/null +++ b/web/images/ballerina-logo.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/web/images/browserconfig.xml b/web/images/browserconfig.xml new file mode 100644 index 0000000..b3930d0 --- /dev/null +++ b/web/images/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #da532c + + + diff --git a/web/images/favicon-16x16.png b/web/images/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..f27c43a7e84c7659368dd7940d8e1d9301f5a63b GIT binary patch literal 563 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^xl_H+M9WCijSl0AZa z85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP=YDR+ueoXe|!I#{Xiaj ziKnkC`(tiSCKJgnNh3d?&<#%)#}JM4YbO|bJ0*&=$p;s2sB`!(F7kJ3hYP!A$Fl_s z|Al)8ES`K_wMj3F&n$Jj>LP_*-oI>lwKQWgU(P*eX*1{ZJaLAPS624rNQKx6H<&*3z<8iywZ!U7Ze)s#a$uGs1N`Ce` zWIWqvf|0V2omfwY=yu!fxrb+M6n_^{$Z26hVX>Wz7!7^5d?)NnbM|2s=ZJsi7YBFek-+x%Xx<0qLeEr!ZpdVFBTq8Jc1ICAEQ%n|m}4IT@;^cY@=3zmFxGMx&v Og2B_(&t;ucLK6URhQwn4 literal 0 HcmV?d00001 diff --git a/web/images/favicon-32x32.png b/web/images/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..fe2ea3d82857cf8d2d03c6641ce563424e873fc8 GIT binary patch literal 808 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UEa{HEjtmSN`?>!lvVtU&J%W50 z7^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+10f+@+{-G$+Qd;gjJKpuOE zr>`sfV{T3+6Ui<~BR>WP#4%K9N%m6YvPm|If^3>DQ?9{HNd%nf-x2+2^WH#K_86J!jI-~Lvyu~NE|;bGCLKp(CjrzVGO=3wxu z@neffP&BG{wvcptHiCL{N1!4 zKn>wlArU1(iRB6fMfqu&IjIUIl?AB^nFS@u3=9=>9)IHDC=AokIOTu(jOWuJ24-b$ zy<~1-Wnu5hBFw@HE)6D!Q<#-EhbWxBaplC3Ge=~Ou%B-5Sm33{@Jd{;RG<|M Mp00i_>zopr0O21$KL7v# literal 0 HcmV?d00001 diff --git a/web/images/favicon.ico b/web/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..cef4c39c06a63af9b244f3c6abc49c7905a28cb9 GIT binary patch literal 15086 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 z + + + +Created by potrace 1.11, written by Peter Selinger 2001-2013 + + + + + + + + + + diff --git a/web/images/site.webmanifest b/web/images/site.webmanifest new file mode 100644 index 0000000..b20abb7 --- /dev/null +++ b/web/images/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "", + "short_name": "", + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/web/src/components/ControlPanel.less b/web/src/components/ControlPanel.less index 2efeb30..9a9f762 100644 --- a/web/src/components/ControlPanel.less +++ b/web/src/components/ControlPanel.less @@ -2,5 +2,10 @@ padding: 5px 10px 5px 10px; .w3-button { margin-right: 10px; + height: 40px; + } + .logo { + height: 40px; + margin-right: 15px; } } \ No newline at end of file diff --git a/web/src/components/ControlPanel.tsx b/web/src/components/ControlPanel.tsx index c37b242..fe84d7d 100644 --- a/web/src/components/ControlPanel.tsx +++ b/web/src/components/ControlPanel.tsx @@ -5,6 +5,8 @@ import { RunButton } from "./RunButton"; export function ControlPanel() { return
+ + diff --git a/web/src/components/OutputPanel.tsx b/web/src/components/OutputPanel.tsx index a7e276e..b81f5a4 100644 --- a/web/src/components/OutputPanel.tsx +++ b/web/src/components/OutputPanel.tsx @@ -29,8 +29,11 @@ export function OutputPanel() { {waitingOnRemoteServer &&
Waiting on remote server
} { responses.map(({ type, data }, index) => { + if (type === "Control" && data === "Executing Program.") { + return
; + } if (type === "Control" && (index !== responses.length - 1)) { - return ; + return; } return (
diff --git a/web/src/index.ejs b/web/src/index.ejs index c7671c2..f189c6e 100644 --- a/web/src/index.ejs +++ b/web/src/index.ejs @@ -3,6 +3,13 @@ + + + + + + + <%= htmlWebpackPlugin.options.title %> diff --git a/web/webpack.config.js b/web/webpack.config.js index 89b73f6..bcf0806 100644 --- a/web/webpack.config.js +++ b/web/webpack.config.js @@ -137,7 +137,8 @@ module.exports = (env, argv) => { CONTROLLER_BACKEND_URL: JSON.stringify(backendUrl) }), new CopyWebpackPlugin([ - {from:'samples', to:'samples'} + {from:'samples', to:'samples'}, + {from:'images', to:'images'} ]) ] }; From 9ab281b9d19b2bf76b063a42fc7d59466ac21b59 Mon Sep 17 00:00:00 2001 From: Kavith Lokuhewage Date: Sat, 9 Nov 2019 08:04:19 +0530 Subject: [PATCH 5/8] Adjust colors of buttons --- web/src/components/ControlPanel.less | 5 +++++ web/src/components/ControlPanel.tsx | 3 +-- web/src/components/OutputPanel.less | 2 +- web/src/components/RunButton.tsx | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/web/src/components/ControlPanel.less b/web/src/components/ControlPanel.less index 9a9f762..f1140fd 100644 --- a/web/src/components/ControlPanel.less +++ b/web/src/components/ControlPanel.less @@ -3,6 +3,11 @@ .w3-button { margin-right: 10px; height: 40px; + outline-style: none; + background-color: #F2F3F4!important; + &:hover { + background-color: white!important; + } } .logo { height: 40px; diff --git a/web/src/components/ControlPanel.tsx b/web/src/components/ControlPanel.tsx index fe84d7d..5898503 100644 --- a/web/src/components/ControlPanel.tsx +++ b/web/src/components/ControlPanel.tsx @@ -5,10 +5,9 @@ import { RunButton } from "./RunButton"; export function ControlPanel() { return
- - +
; diff --git a/web/src/components/OutputPanel.less b/web/src/components/OutputPanel.less index 7b3e1bc..83f2cee 100644 --- a/web/src/components/OutputPanel.less +++ b/web/src/components/OutputPanel.less @@ -7,7 +7,7 @@ color: gray; } .data { - color: brown; + color: gray; } .error { color: red; diff --git a/web/src/components/RunButton.tsx b/web/src/components/RunButton.tsx index cedad2f..a873a57 100644 --- a/web/src/components/RunButton.tsx +++ b/web/src/components/RunButton.tsx @@ -6,7 +6,7 @@ export function RunButton() { return { ({ onRun, runInProgress }) => ( - +
; } diff --git a/web/src/components/OutputPanel.less b/web/src/components/OutputPanel.less index 83f2cee..52026a1 100644 --- a/web/src/components/OutputPanel.less +++ b/web/src/components/OutputPanel.less @@ -7,9 +7,38 @@ color: gray; } .data { + &.output { + color: #1f1f1f; + } color: gray; } .error { color: red; } -} \ No newline at end of file + .loading { + span { + animation-name: blink; + animation-duration: 1.4s; + animation-iteration-count: infinite; + animation-fill-mode: both; + } + span:nth-child(2) { + animation-delay: .2s; + } + span:nth-child(3) { + animation-delay: .4s; + } + } +} + +@keyframes blink { + 0% { + opacity: .2; + } + 20% { + opacity: 1; + } + 100% { + opacity: .2; + } +} diff --git a/web/src/components/OutputPanel.tsx b/web/src/components/OutputPanel.tsx index b81f5a4..51e6da7 100644 --- a/web/src/components/OutputPanel.tsx +++ b/web/src/components/OutputPanel.tsx @@ -2,19 +2,31 @@ import * as React from "react"; import "./OutputPanel.less"; import { PlaygroundContext } from "./Playground"; +export function createLoadingAnimation(text: string) { + if (text.endsWith("...")) { + return {text.replace("...", "")} + ...; + } else { + return text; + } +} + export function createHTMLFormattedText(text: string) { - return text.split(/\n/g).map((val) => { + return text.split(/\n/g).map((val, index, array) => { + if (index === array.length - 1 && val === "") { + return; + } const tabbedPieces = val.split(/\t/g); return (
{ - tabbedPieces.length === 1 && {val} + tabbedPieces.length === 1 && {createLoadingAnimation(val)} } { tabbedPieces.length > 1 && tabbedPieces .map((tabbedSegment) => -     {tabbedSegment}, +     {createLoadingAnimation(tabbedSegment)}, ) }
@@ -22,27 +34,50 @@ export function createHTMLFormattedText(text: string) { }); } +export function getOutputMsg(data: string) { + let msg = data; + switch (data) { + case "Finished Executing.": + msg = "execution complete."; break; + case "Compiling Program.": + msg = "compiling..."; break; + case "Finished Compiling with errors.": + msg = "compilation failed :("; break; + case "Executing Program.": + msg = "executing..."; break; + } + return msg; +} + export function OutputPanel() { return - {({ responses, waitingOnRemoteServer }) => ( -
- {waitingOnRemoteServer &&
Waiting on remote server
} + {({ responses, waitingOnRemoteServer }) => { + let inExecutionPhase = false; + return
+ {waitingOnRemoteServer && +
{createLoadingAnimation("waiting on remote server...")}
} { responses.map(({ type, data }, index) => { - if (type === "Control" && data === "Executing Program.") { + if (type === "Control" && data === "Finished Compiling.") { return
; } + if (type === "Control" && data === "Executing Program.") { + inExecutionPhase = true; + } if (type === "Control" && (index !== responses.length - 1)) { return; } return ( -
- {createHTMLFormattedText(data)} +
+ {data === "Finished Executing." &&
} + {data === "Finished Compiling with errors." &&
} + {createHTMLFormattedText(getOutputMsg(data))} + {data === "Finished Executing." &&




}
); }) } -
- )} +
; + }} ; } From 5b3b024504ad80d09d4b3940389985cfcb5223ce Mon Sep 17 00:00:00 2001 From: Kavith Lokuhewage Date: Sat, 9 Nov 2019 18:42:00 +0530 Subject: [PATCH 7/8] Add debug logs in compiler & executor apis --- api/compiler/src/playground_compiler/compile.bal | 16 +++++++++++++++- api/executor/src/playground_executor/execute.bal | 11 ++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/api/compiler/src/playground_compiler/compile.bal b/api/compiler/src/playground_compiler/compile.bal index 97ddafd..866946d 100644 --- a/api/compiler/src/playground_compiler/compile.bal +++ b/api/compiler/src/playground_compiler/compile.bal @@ -1,6 +1,7 @@ import ballerina/file; import ballerina/filepath; import ballerina/io; +import ballerina/log; const buildCacheDir = "/build-cache"; @@ -13,37 +14,50 @@ const buildCacheDir = "/build-cache"; # function createSourceFile(string cacheId, string sourceCode) returns string|error { if (file:exists(buildCacheDir)) { + log:printDebug("Build cache is mounted. " ); string cachedBuildDir = check filepath:build(buildCacheDir, cacheId); string cachedAppPath = check filepath:build(buildCacheDir, cacheId, "app.bal"); if (!file:exists(cachedBuildDir)) { + log:printDebug("Creating source file for compilation. " + cachedAppPath); io:WritableByteChannel appFile = check io:openWritableFile(cachedAppPath); _ = check appFile.write(sourceCode.toBytes(), 0); check appFile.close(); + } else { + log:printDebug("Found existing source file for compilation. " + cachedAppPath); } return cachedAppPath; } else { + log:printError("Build cache is not mounted. " ); return file:FileNotFoundError( message = "Build Cache Directory " + buildCacheDir + " not found."); } } function compile(CompileData data) returns CompilerResponse|error { + log:printDebug("Compiling request: " + data.toString()); string? cacheId = getCacheId(data.sourceCode, data.balVersion); if (cacheId is string) { boolean hasCachedOutputResult = hasCachedOutput(cacheId); + log:printDebug("Searching for cached output. Cache ID: " + cacheId); if (hasCachedOutputResult) { string? cachedOutput = getCachedOutput(cacheId); if (cachedOutput is string) { + log:printDebug("Found cached output. " + cachedOutput); return createDataResponse(cachedOutput); } else { + log:printError("Empty cached output returned. " ); return createErrorResponse("Invalid cached output returned from cache."); } } else { + log:printDebug("Cached output not found."); string sourceFile = check createSourceFile(cacheId, data.sourceCode); string buildDir = check filepath:parent(sourceFile); + log:printDebug("Using " + sourceFile + " for compilation."); string|error execStatus = execBallerinaCmd(buildDir, "build", "app.bal"); if (execStatus is error) { - return createErrorResponse(execStatus.reason()); + log:printError("Error while executing compile command. ", execStatus); + return createErrorResponse(execStatus.reason()); } else { + log:printDebug("Finished executing compile command. Output: " + execStatus); string jarPath = check filepath:build(buildDir, "app.jar"); setCachedOutput(cacheId, execStatus); return createDataResponse(execStatus); diff --git a/api/executor/src/playground_executor/execute.bal b/api/executor/src/playground_executor/execute.bal index 0ebf5b2..bd96eba 100644 --- a/api/executor/src/playground_executor/execute.bal +++ b/api/executor/src/playground_executor/execute.bal @@ -1,5 +1,7 @@ import ballerina/file; import ballerina/filepath; +import ballerina/log; + const buildCacheDir = "/build-cache"; function getAppJar(string cacheId) returns string|error { @@ -16,23 +18,30 @@ function getAppJar(string cacheId) returns string|error { } function execute(ExecuteData data) returns ExecutorResponse|error { + log:printDebug("Executing request: " + data.toString()); string? cacheId = getCacheId(data.sourceCode, data.balVersion); if (cacheId is string) { + log:printDebug("Searching for cached output. Cache ID: " + cacheId); boolean hasCachedOutputResult = hasCachedOutput(cacheId); if (hasCachedOutputResult) { string? cachedOutput = getCachedOutput(cacheId); if (cachedOutput is string) { + log:printDebug("Found cached output. " + cachedOutput); return createDataResponse(cachedOutput); } else { return createErrorResponse("Invalid cached output returned from cache."); } } else { + log:printDebug("Cached output not found."); string appJar = check getAppJar(cacheId); + log:printDebug("Executing jar: " + appJar); string cwd = check filepath:parent(appJar); string|error execStatus = execJar(cwd, appJar); if (execStatus is error) { - return createErrorResponse(execStatus.reason()); + log:printError("Error while executing jar: " + execStatus.reason()); + return createErrorResponse(execStatus.reason()); } else { + log:printDebug("Executed jar: " + execStatus); setCachedOutput(cacheId, execStatus); return createDataResponse(execStatus); } From e5cc2a18ded954d42c034f95ed7cb6ecf8344eba Mon Sep 17 00:00:00 2001 From: Kavith Lokuhewage Date: Sat, 9 Nov 2019 18:42:31 +0530 Subject: [PATCH 8/8] Increase no of replicas in prod instance --- k8s/compiler/compiler-deployment.yaml | 2 +- k8s/controller/controller-deployment.yaml | 2 +- k8s/executor/executor-deployment.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/k8s/compiler/compiler-deployment.yaml b/k8s/compiler/compiler-deployment.yaml index 024a2b9..4c4914b 100644 --- a/k8s/compiler/compiler-deployment.yaml +++ b/k8s/compiler/compiler-deployment.yaml @@ -5,7 +5,7 @@ metadata: labels: app: ballerina-playground-compiler spec: - replicas: 2 + replicas: 6 selector: matchLabels: app: ballerina-playground-compiler diff --git a/k8s/controller/controller-deployment.yaml b/k8s/controller/controller-deployment.yaml index a9d3901..b9e45d5 100644 --- a/k8s/controller/controller-deployment.yaml +++ b/k8s/controller/controller-deployment.yaml @@ -5,7 +5,7 @@ metadata: labels: app: ballerina-playground-controller spec: - replicas: 2 + replicas: 4 selector: matchLabels: app: ballerina-playground-controller diff --git a/k8s/executor/executor-deployment.yaml b/k8s/executor/executor-deployment.yaml index 93e1fbd..b6c7855 100644 --- a/k8s/executor/executor-deployment.yaml +++ b/k8s/executor/executor-deployment.yaml @@ -5,7 +5,7 @@ metadata: labels: app: ballerina-playground-executor spec: - replicas: 2 + replicas: 6 selector: matchLabels: app: ballerina-playground-executor