This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/texera.git
The following commit(s) were added to refs/heads/main by this push:
new 4b526eb26a chore(amber): remove the unused EmptyReplayLogger (#7452)
4b526eb26a is described below
commit 4b526eb26afcce34467d50b6ff597f4f06642dde
Author: Xinyuan Lin <[email protected]>
AuthorDate: Sat Aug 15 02:01:18 2026 +0000
chore(amber): remove the unused EmptyReplayLogger (#7452)
### What changes were proposed in this PR?
Deletes `EmptyReplayLogger` and its spec — a no-op `ReplayLogger` that
nothing in the engine ever constructs. Pure deletion, no behaviour
change: **−171 lines**.
The live null object for log replay sits one layer up, at the manager.
`EmptyReplayLogManagerImpl` inherits the `ReplayLogManager` trait's
non-logging `withFaultTolerant`, so it never needs a logger at all:
```
ReplayLogManager.scala:51 -> EmptyReplayLogManagerImpl (no-op manager,
live)
ReplayLogManager.scala:109 -> new ReplayLoggerImpl() (the only
ReplayLogger built in main)
EmptyReplayLogger (never
instantiated)
```
`69b7f9bc1` (#2230) added `ReplayLogger`, `ReplayLoggerImpl`,
`EmptyReplayLogger` and `ReplayLogManager` in a single commit, so
nothing ever moved layers — `EmptyReplayLogger` was unwired from the day
it landed. No configuration selects a logger class by name either, so
there is no path that revives it.
> Reviewer note: the abstract base `ReplayLogger` is **not** touched —
`ReplayLoggerImpl` extends it and is unaffected. It does end up with a
single subclass and no declared-type site once this lands, so collapsing
it is tracked separately in #7673; that one edits live code, while this
PR stays a pure dead-code deletion. `EmptyReplayLogger` acquired unit
tests during the 2026 coverage work (#5554), which is why it currently
looks live; the spec covers this class and nothing else.
### Any related issues, documentation, discussions?
Closes #7449
### How was this PR tested?
Existing tests only — this PR adds none, since it removes code and the
spec that covered it.
Locally, from the repo root with Java 17:
- `sbt "WorkflowExecutionService/Test/compile"` — success.
Verification, re-runnable by a reviewer:
```
git grep -n EmptyReplayLogger # only the two
deleted files
git grep -n "extends ReplayLogger" -- amber/src/main # ReplayLoggerImpl
remains
git log -S "new EmptyReplayLogger" --all # only the #5554
spec commits
```
### Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Claude Opus 5)
---
.../architecture/logreplay/EmptyReplayLogger.scala | 41 -------
.../logreplay/EmptyReplayLoggerSpec.scala | 130 ---------------------
2 files changed, 171 deletions(-)
diff --git
a/amber/src/main/scala/org/apache/texera/amber/engine/architecture/logreplay/EmptyReplayLogger.scala
b/amber/src/main/scala/org/apache/texera/amber/engine/architecture/logreplay/EmptyReplayLogger.scala
deleted file mode 100644
index 74be96acdb..0000000000
---
a/amber/src/main/scala/org/apache/texera/amber/engine/architecture/logreplay/EmptyReplayLogger.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.texera.amber.engine.architecture.logreplay
-
-import org.apache.texera.amber.core.virtualidentity.{
- ChannelIdentity,
- EmbeddedControlMessageIdentity
-}
-import org.apache.texera.amber.engine.common.ambermessage.WorkflowFIFOMessage
-
-class EmptyReplayLogger extends ReplayLogger {
-
- override def drainCurrentLogRecords(step: Long): Array[ReplayLogRecord] = {
- Array.empty
- }
-
- def markAsReplayDestination(id: EmbeddedControlMessageIdentity): Unit = {}
-
- override def logCurrentStepWithMessage(
- step: Long,
- channelId: ChannelIdentity,
- msg: Option[WorkflowFIFOMessage]
- ): Unit = {}
-}
diff --git
a/amber/src/test/scala/org/apache/texera/amber/engine/architecture/logreplay/EmptyReplayLoggerSpec.scala
b/amber/src/test/scala/org/apache/texera/amber/engine/architecture/logreplay/EmptyReplayLoggerSpec.scala
deleted file mode 100644
index ccd7fde8f9..0000000000
---
a/amber/src/test/scala/org/apache/texera/amber/engine/architecture/logreplay/EmptyReplayLoggerSpec.scala
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.texera.amber.engine.architecture.logreplay
-
-import org.apache.texera.amber.core.virtualidentity.{
- ActorVirtualIdentity,
- ChannelIdentity,
- EmbeddedControlMessageIdentity
-}
-import org.scalatest.flatspec.AnyFlatSpec
-
-class EmptyReplayLoggerSpec extends AnyFlatSpec {
-
- //
---------------------------------------------------------------------------
- // Fixtures
- //
---------------------------------------------------------------------------
-
- private val channelId: ChannelIdentity =
- ChannelIdentity(ActorVirtualIdentity("from"), ActorVirtualIdentity("to"),
isControl = false)
- private val ecmId: EmbeddedControlMessageIdentity =
EmbeddedControlMessageIdentity("test-ecm")
-
- //
---------------------------------------------------------------------------
- // drainCurrentLogRecords — always empty
- //
---------------------------------------------------------------------------
-
- "EmptyReplayLogger.drainCurrentLogRecords" should
- "return an empty Array[ReplayLogRecord] regardless of the step argument"
in {
- val logger = new EmptyReplayLogger
- val r0 = logger.drainCurrentLogRecords(0L)
- val r1 = logger.drainCurrentLogRecords(1L)
- val rMax = logger.drainCurrentLogRecords(Long.MaxValue)
- val rNeg = logger.drainCurrentLogRecords(-1L)
- assert(r0.isEmpty)
- assert(r1.isEmpty)
- assert(rMax.isEmpty)
- assert(rNeg.isEmpty)
- }
-
- it should "return a non-null array (callers iterate it without
null-checking)" in {
- val logger = new EmptyReplayLogger
- val r = logger.drainCurrentLogRecords(42L)
- assert(r != null)
- assert(r.length == 0)
- }
-
- it should "return arrays whose element type is ReplayLogRecord (compile-time
enforced)" in {
- // If a future refactor accidentally widened the return type to
- // `Array[AnyRef]`, this would fail to typecheck. Pin the contract.
- val logger = new EmptyReplayLogger
- val r: Array[ReplayLogRecord] = logger.drainCurrentLogRecords(0L)
- assert(r.length == 0)
- }
-
- //
---------------------------------------------------------------------------
- // markAsReplayDestination — no-op
- //
---------------------------------------------------------------------------
-
- "EmptyReplayLogger.markAsReplayDestination" should
- "accept any EmbeddedControlMessageIdentity without throwing" in {
- val logger = new EmptyReplayLogger
- logger.markAsReplayDestination(ecmId) // must not throw
- // Calling twice with the same id is still a no-op.
- logger.markAsReplayDestination(ecmId)
- succeed
- }
-
- it should "leave drainCurrentLogRecords output untouched (no internal buffer
accumulates)" in {
- val logger = new EmptyReplayLogger
- logger.markAsReplayDestination(ecmId)
- logger.markAsReplayDestination(EmbeddedControlMessageIdentity("another"))
- assert(logger.drainCurrentLogRecords(0L).isEmpty)
- }
-
- //
---------------------------------------------------------------------------
- // logCurrentStepWithMessage — no-op
- //
---------------------------------------------------------------------------
-
- "EmptyReplayLogger.logCurrentStepWithMessage" should
- "accept any (step, channelId, msg) triple without throwing" in {
- val logger = new EmptyReplayLogger
- logger.logCurrentStepWithMessage(0L, channelId, msg = None)
- logger.logCurrentStepWithMessage(1L, channelId, msg = None)
- logger.logCurrentStepWithMessage(Long.MaxValue, channelId, msg = None)
- succeed
- }
-
- it should "tolerate a None msg argument (the null-object's job is to absorb
every call)" in {
- val logger = new EmptyReplayLogger
- logger.logCurrentStepWithMessage(7L, channelId, msg = None)
- // Verify nothing was queued in the process.
- assert(logger.drainCurrentLogRecords(7L).isEmpty)
- }
-
- it should "leave drainCurrentLogRecords output empty even after many calls"
in {
- val logger = new EmptyReplayLogger
- (1L to 100L).foreach(i => logger.logCurrentStepWithMessage(i, channelId,
msg = None))
- assert(logger.drainCurrentLogRecords(100L).isEmpty)
- }
-
- //
---------------------------------------------------------------------------
- // ReplayLogger trait conformance
- //
---------------------------------------------------------------------------
- //
- // The null-object pattern requires EmptyReplayLogger to be a drop-in for
- // ReplayLogger callers — pin the upcast.
-
- "EmptyReplayLogger" should "be usable through the ReplayLogger interface" in
{
- val logger: ReplayLogger = new EmptyReplayLogger
- logger.logCurrentStepWithMessage(0L, channelId, msg = None)
- logger.markAsReplayDestination(ecmId)
- assert(logger.drainCurrentLogRecords(0L).isEmpty)
- }
-}