diff --git a/amber/src/main/scala/org/apache/texera/amber/engine/architecture/controller/Controller.scala b/amber/src/main/scala/org/apache/texera/amber/engine/architecture/controller/Controller.scala index b0e4f3fdc32..daa977d8575 100644 --- a/amber/src/main/scala/org/apache/texera/amber/engine/architecture/controller/Controller.scala +++ b/amber/src/main/scala/org/apache/texera/amber/engine/architecture/controller/Controller.scala @@ -199,8 +199,7 @@ class Controller( override def handleBackpressure(isBackpressured: Boolean): Unit = {} - // adopted solution from - // https://stackoverflow.com/questions/54228901/right-way-of-exception-handling-when-using-akka-actors + // Use AllForOneStrategy to stop all children on any fatal error and report it to the client. override val supervisorStrategy: SupervisorStrategy = AllForOneStrategy(maxNrOfRetries = 0, withinTimeRange = 1.minute) { case e: Throwable => diff --git a/amber/src/main/scala/org/apache/texera/web/ServletAwareConfigurator.scala b/amber/src/main/scala/org/apache/texera/web/ServletAwareConfigurator.scala index 66a4521064a..cb3628df5b3 100644 --- a/amber/src/main/scala/org/apache/texera/web/ServletAwareConfigurator.scala +++ b/amber/src/main/scala/org/apache/texera/web/ServletAwareConfigurator.scala @@ -33,12 +33,9 @@ import javax.websocket.server.{HandshakeRequest, ServerEndpointConfig} import scala.jdk.CollectionConverters.{ListHasAsScala, _} /** - * This configurator extracts HTTPSession and associates it to ServerEndpointConfig, - * allow it to be accessed by Websocket connections. - *
-  * See 
-  * 
+ * This configurator extracts user identity from the HTTP handshake request + * and associates it with the ServerEndpointConfig, allowing it to be + * accessed by WebSocket connections. */ class ServletAwareConfigurator extends ServerEndpointConfig.Configurator with LazyLogging { diff --git a/common/workflow-core/src/main/scala/org/apache/texera/amber/core/workflow/PhysicalOp.scala b/common/workflow-core/src/main/scala/org/apache/texera/amber/core/workflow/PhysicalOp.scala index 0ac04c7a630..494fd6f76dc 100644 --- a/common/workflow-core/src/main/scala/org/apache/texera/amber/core/workflow/PhysicalOp.scala +++ b/common/workflow-core/src/main/scala/org/apache/texera/amber/core/workflow/PhysicalOp.scala @@ -158,8 +158,8 @@ object PhysicalOp { } } -// @JsonIgnore is not working when directly annotated to fields of a case class -// https://stackoverflow.com/questions/40482904/jsonignore-doesnt-work-in-scala-case-class +// In Scala case classes, @JsonIgnore on constructor parameters is not recognized by Jackson. +// Use @JsonIgnoreProperties at the class level instead. @JsonIgnoreProperties( Array( "opExecInitInfo", // function type, ignore it diff --git a/common/workflow-operator/src/main/scala/com/kjetland/jackson/jsonSchema/JsonSchemaGenerator.scala b/common/workflow-operator/src/main/scala/com/kjetland/jackson/jsonSchema/JsonSchemaGenerator.scala index 395de278997..c3e9a0c30d7 100644 --- a/common/workflow-operator/src/main/scala/com/kjetland/jackson/jsonSchema/JsonSchemaGenerator.scala +++ b/common/workflow-operator/src/main/scala/com/kjetland/jackson/jsonSchema/JsonSchemaGenerator.scala @@ -1483,17 +1483,33 @@ class JsonSchemaGenerator( } def generateTitleFromPropertyName(propertyName: String): String = { - // Code found here: http://stackoverflow.com/questions/2559759/how-do-i-convert-camelcase-into-human-readable-names-in-java - val s = propertyName.replaceAll( - String.format( - "%s|%s|%s", - "(?<=[A-Z])(?=[A-Z][a-z])", - "(?<=[^A-Z])(?=[A-Z])", - "(?<=[A-Za-z])(?=[^A-Za-z])" - ), - " " - ) + // Insert spaces at camelCase/PascalCase boundaries and letter-to-non-letter transitions. + val builder = new StringBuilder + for (i <- propertyName.indices) { + val c = propertyName(i) + if (i > 0) { + val prev = propertyName(i - 1) + val isCurrentUpper = c.isUpper + val isPrevUpper = prev.isUpper + val isPrevLetter = prev.isLetter + val isCurrentLetter = c.isLetter + val nextIsLower = i + 1 < propertyName.length && propertyName(i + 1).isLower + + // Space before uppercase that follows a non-uppercase char (e.g., "camelCase" or "123Value") + // Space before uppercase in an acronym run when next char is lowercase (e.g., "XMLParser") + // Space before a non-letter that follows a letter (e.g., "test123") + if ( + (isCurrentUpper && !isPrevUpper) || + (isCurrentUpper && isPrevUpper && nextIsLower) || + (!isCurrentLetter && isPrevLetter) + ) { + builder.append(' ') + } + } + builder.append(c) + } + val s = builder.toString() // Make the first letter uppercase s.substring(0, 1).toUpperCase() + s.substring(1) } diff --git a/frontend/custom-webpack.config.js b/frontend/custom-webpack.config.js index df1d742b920..e80fa3a45b2 100644 --- a/frontend/custom-webpack.config.js +++ b/frontend/custom-webpack.config.js @@ -29,8 +29,8 @@ module.exports = { ], }, ], - // this is required for loading .wasm (and other) files. - // For context, see https://stackoverflow.com/a/75252098 and https://github.com/angular/angular-cli/issues/24617 + // Enable URL handling in webpack's JavaScript parser, required for loading .wasm files. + // See https://github.com/angular/angular-cli/issues/24617 parser: { javascript: { url: true, diff --git a/frontend/src/app/common/service/user/auth.service.ts b/frontend/src/app/common/service/user/auth.service.ts index 72f443cb273..5b7f38d5701 100644 --- a/frontend/src/app/common/service/user/auth.service.ts +++ b/frontend/src/app/common/service/user/auth.service.ts @@ -175,11 +175,11 @@ export class AuthService { const expirationTime = this.jwtHelperService.getTokenExpirationDate()?.getTime(); const token = AuthService.getAccessToken(); if (token !== null && !this.jwtHelperService.isTokenExpired(token) && expirationTime !== undefined) { - // use timer with ignoreElements to avoid event being immediately triggered (in RxJS 7) - // see https://stackoverflow.com/questions/70013573/how-to-replicate-delay-from-rxjs-6-x + // In RxJS 7, timer emits immediately then completes. Using ignoreElements() suppresses + // the emitted value so the complete callback fires only after the specified delay. this.tokenExpirationSubscription = timer(expirationTime - new Date().getTime()) .pipe(ignoreElements()) - .subscribe(() => this.logout()); + .subscribe({ complete: () => this.logout() }); } } diff --git a/frontend/src/app/common/type/generic-web-response.ts b/frontend/src/app/common/type/generic-web-response.ts index e79d473c00e..c354b10e9b5 100644 --- a/frontend/src/app/common/type/generic-web-response.ts +++ b/frontend/src/app/common/type/generic-web-response.ts @@ -18,9 +18,8 @@ */ /** - * make sure do not add const/declare before enum here. - * Const enums are removed during transpiration in JS so you can not use them at runtime. - * Source: https://stackoverflow.com/questions/50365598/typescript-runtime-error-cannot-read-property-of-undefined-enum + * Do not use `const enum` here. Const enums are inlined at compile time and removed + * from the emitted JavaScript, which causes runtime errors if the enum is accessed dynamically. */ export enum GenericWebResponseCode { SUCCESS = 0,