chihsuan commented on code in PR #11262:
URL: https://github.com/apache/ozone/pull/11262#discussion_r4052391717


##########
hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/tasks/ReconTaskControllerImpl.java:
##########
@@ -502,6 +502,65 @@ private void processTasks(
     } catch (CancellationException ce) {
       LOG.error("Some tasks were cancelled with exception", ce);
     }
+
+    failedTasks.addAll(executionFailedTasks);
+
+    if (!successfulTasks.isEmpty()) {
+      // Make the derived-table RocksDB writes for this batch durable before 
the task-status
+      // cursors are committed to Derby. The cursor rows are fsync-durable 
while the RocksDB writes
+      // are not synced by default, so without this barrier a power loss can 
leave the durable
+      // cursors ahead of the (lost) derived data. Startup reconciliation then 
sees the derived
+      // and delta cursors at the same sequence number and never reprocesses, 
permanently
+      // dropping the applied update. Coalescing the barrier to once per batch 
syncs all successful
+      // task writes together before any cursor advances. If the sync fails, 
leave the cursors
+      // unadvanced so the batch is reprocessed instead of recording an 
un-durable success.
+      if (syncReconDbLog()) {
+        for (ReconOmTask.TaskResult result : successfulTasks) {
+          String taskName = result.getTaskName();
+          // Track task delta processing success
+          taskMetrics.incrTaskDeltaProcessingSuccess(taskName);
+
+          ReconTaskStatusUpdater taskStatusUpdater =
+              taskStatusUpdaterManager.getTaskStatusUpdater(taskName);
+          taskStatusUpdater.setLastTaskRunStatus(0);
+          
taskStatusUpdater.setLastUpdatedSeqNumber(events.getLastSequenceNumber());
+          taskStatusUpdater.recordRunCompletion();
+        }
+      } else {
+        for (ReconOmTask.TaskResult result : successfulTasks) {
+          String taskName = result.getTaskName();
+          failedTasks.add(new ReconOmTask.TaskResult.Builder()

Review Comment:
   Should we signal reinit here instead of re-running process()? I noticed the 
task already committed this batch, so the retry applies the same events twice. 
With a transient sync failure, a counting task ends up double counted and the 
cursor still advances.



##########
hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/tasks/ReconTaskControllerImpl.java:
##########
@@ -502,6 +502,65 @@ private void processTasks(
     } catch (CancellationException ce) {
       LOG.error("Some tasks were cancelled with exception", ce);
     }
+
+    failedTasks.addAll(executionFailedTasks);
+
+    if (!successfulTasks.isEmpty()) {
+      // Make the derived-table RocksDB writes for this batch durable before 
the task-status
+      // cursors are committed to Derby. The cursor rows are fsync-durable 
while the RocksDB writes
+      // are not synced by default, so without this barrier a power loss can 
leave the durable
+      // cursors ahead of the (lost) derived data. Startup reconciliation then 
sees the derived
+      // and delta cursors at the same sequence number and never reprocesses, 
permanently
+      // dropping the applied update. Coalescing the barrier to once per batch 
syncs all successful
+      // task writes together before any cursor advances. If the sync fails, 
leave the cursors
+      // unadvanced so the batch is reprocessed instead of recording an 
un-durable success.
+      if (syncReconDbLog()) {
+        for (ReconOmTask.TaskResult result : successfulTasks) {
+          String taskName = result.getTaskName();
+          // Track task delta processing success
+          taskMetrics.incrTaskDeltaProcessingSuccess(taskName);
+
+          ReconTaskStatusUpdater taskStatusUpdater =
+              taskStatusUpdaterManager.getTaskStatusUpdater(taskName);
+          taskStatusUpdater.setLastTaskRunStatus(0);
+          
taskStatusUpdater.setLastUpdatedSeqNumber(events.getLastSequenceNumber());
+          taskStatusUpdater.recordRunCompletion();
+        }
+      } else {
+        for (ReconOmTask.TaskResult result : successfulTasks) {
+          String taskName = result.getTaskName();
+          failedTasks.add(new ReconOmTask.TaskResult.Builder()
+              .setTaskName(taskName)
+              .setSubTaskSeekPositions(result.getSubTaskSeekPositions())
+              .build());
+          ReconTaskStatusUpdater taskStatusUpdater =
+              taskStatusUpdaterManager.getTaskStatusUpdater(taskName);
+          taskStatusUpdater.setLastTaskRunStatus(-1);
+          taskStatusUpdater.recordRunCompletion();
+        }
+      }
+    }
+  }
+
+  /**
+   * Flushes and syncs the Recon derived-data RocksDB write-ahead log to 
stable storage so the
+   * derived writes for the processed batch are durable before the task-status 
cursor advances.
+   * Returns {@code false} if the sync fails, in which case the caller must 
not advance the cursor,
+   * so that the cursor is never persisted ahead of the derived data.
+   */
+  private boolean syncReconDbLog() {
+    DBStore dbStore = reconDBProvider.getDbStore();
+    if (dbStore == null) {
+      return true;

Review Comment:
   nit: Should a null dbStore return false here? Treating it as synced advances 
the cursor without any durability guarantee, though I realize this is mostly 
unreachable in practice.



##########
hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/tasks/ReconTaskControllerImpl.java:
##########
@@ -502,6 +502,65 @@ private void processTasks(
     } catch (CancellationException ce) {
       LOG.error("Some tasks were cancelled with exception", ce);
     }
+
+    failedTasks.addAll(executionFailedTasks);
+
+    if (!successfulTasks.isEmpty()) {
+      // Make the derived-table RocksDB writes for this batch durable before 
the task-status
+      // cursors are committed to Derby. The cursor rows are fsync-durable 
while the RocksDB writes
+      // are not synced by default, so without this barrier a power loss can 
leave the durable
+      // cursors ahead of the (lost) derived data. Startup reconciliation then 
sees the derived
+      // and delta cursors at the same sequence number and never reprocesses, 
permanently
+      // dropping the applied update. Coalescing the barrier to once per batch 
syncs all successful
+      // task writes together before any cursor advances. If the sync fails, 
leave the cursors
+      // unadvanced so the batch is reprocessed instead of recording an 
un-durable success.
+      if (syncReconDbLog()) {
+        for (ReconOmTask.TaskResult result : successfulTasks) {
+          String taskName = result.getTaskName();
+          // Track task delta processing success
+          taskMetrics.incrTaskDeltaProcessingSuccess(taskName);
+
+          ReconTaskStatusUpdater taskStatusUpdater =
+              taskStatusUpdaterManager.getTaskStatusUpdater(taskName);
+          taskStatusUpdater.setLastTaskRunStatus(0);
+          
taskStatusUpdater.setLastUpdatedSeqNumber(events.getLastSequenceNumber());
+          taskStatusUpdater.recordRunCompletion();
+        }
+      } else {
+        for (ReconOmTask.TaskResult result : successfulTasks) {
+          String taskName = result.getTaskName();
+          failedTasks.add(new ReconOmTask.TaskResult.Builder()
+              .setTaskName(taskName)
+              .setSubTaskSeekPositions(result.getSubTaskSeekPositions())
+              .build());
+          ReconTaskStatusUpdater taskStatusUpdater =
+              taskStatusUpdaterManager.getTaskStatusUpdater(taskName);
+          taskStatusUpdater.setLastTaskRunStatus(-1);

Review Comment:
   nit: Would it be worth counting this as a failure in taskMetrics too? Right 
now a sync failure is invisible to anyone alerting on the delta metrics.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to