All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.camunda.zeebe.snapshots.impl.FileBasedSnapshotId Maven / Gradle / Ivy

There is a newer version: 8.7.0-alpha2-rc1
Show newest version
/*
 * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under
 * one or more contributor license agreements. See the NOTICE file distributed
 * with this work for additional information regarding copyright ownership.
 * Licensed under the Zeebe Community License 1.1. You may not use this file
 * except in compliance with the Zeebe Community License 1.1.
 */
package io.camunda.zeebe.snapshots.impl;

import io.camunda.zeebe.snapshots.SnapshotId;
import java.nio.file.Path;
import java.util.Objects;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class FileBasedSnapshotId implements SnapshotId {
  private static final Logger LOGGER = LoggerFactory.getLogger(FileBasedSnapshotId.class);
  private static final int SNAPSHOT_ID_PARTS = 4;

  private final long index;
  private final long term;
  private final long processedPosition;
  private final long exporterPosition;

  FileBasedSnapshotId(
      final long index,
      final long term,
      final long processedPosition,
      final long exporterPosition) {
    this.index = index;
    this.term = term;
    this.processedPosition = processedPosition;
    this.exporterPosition = exporterPosition;
  }

  // TODO(npepinpe): using Either here would improve readability and observability, as validation
  //  can have better error messages, and the return type better expresses what we attempt to do,
  //  i.e. either it failed (with an error) or it succeeded
  public static Optional ofPath(final Path path) {
    return ofFileName(path.getFileName().toString());
  }

  public static Optional ofFileName(final String name) {
    final var parts = name.split("-");
    Optional snapshotId = Optional.empty();

    if (parts.length >= SNAPSHOT_ID_PARTS) {
      try {
        final var index = Long.parseLong(parts[0]);
        final var term = Long.parseLong(parts[1]);
        final var processedPosition = Long.parseLong(parts[2]);
        final var exporterPosition = Long.parseLong(parts[3]);

        snapshotId =
            Optional.of(new FileBasedSnapshotId(index, term, processedPosition, exporterPosition));
      } catch (final NumberFormatException e) {
        LOGGER.warn("Failed to parse part of snapshot id", e);
      }
    } else {
      LOGGER.warn("Expected snapshot file format to be %d-%d-%d-%d, but was {}", name);
    }

    return snapshotId;
  }

  @Override
  public long getIndex() {
    return index;
  }

  @Override
  public long getTerm() {
    return term;
  }

  @Override
  public long getProcessedPosition() {
    return processedPosition;
  }

  @Override
  public long getExportedPosition() {
    return exporterPosition;
  }

  @Override
  public String getSnapshotIdAsString() {
    return String.format(
        "%d-%d-%d-%d", getIndex(), getTerm(), getProcessedPosition(), getExportedPosition());
  }

  @Override
  public int hashCode() {
    return Objects.hash(index, term, processedPosition, exporterPosition);
  }

  @Override
  public boolean equals(final Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    final FileBasedSnapshotId that = (FileBasedSnapshotId) o;
    return index == that.index
        && term == that.term
        && processedPosition == that.processedPosition
        && exporterPosition == that.exporterPosition;
  }

  @Override
  public String toString() {
    return "FileBasedSnapshotId{"
        + "index="
        + index
        + ", term="
        + term
        + ", processedPosition="
        + processedPosition
        + ", exporterPosition="
        + exporterPosition
        + '}';
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy