Class SchemaVersionCounter

java.lang.Object
org.gcube.informationsystem.resourceregistry.cluster.SchemaVersionCounter

public class SchemaVersionCounter extends Object
The schema version: a monotonic counter, persisted as RegistryMetadata.revisionCount, that advances every time the Type schema is written.

Why it exists. ClusterEventBus buys latency, not correctness: neither of its channels guarantees delivery. A projection that missed an event would otherwise stay stale forever, since nothing would retry until an unrelated change happened to occur. Comparing the version a projection was built from against the current one turns that into a self-healing condition, checked on a rare heartbeat rather than on every read.

Why it is persisted. Redis would lose the counter on a flush or a restart, leaving instances unable to tell that anything changed — or, worse, seeing it go backwards. The database holds it; Redis only a copy, to keep it cheap to read.

The increment is a single server-side update, atomic in the database, so concurrent increments from different instances cannot lose each other the way a read-modify-write would.

Author:
Luca Frosini (ISTI - CNR)
  • Field Details

    • UNKNOWN_VERSION

      public static final long UNKNOWN_VERSION
      Returned by getCurrentVersion() when the counter cannot be read at all. Distinct from any real version, so a caller can tell "unknown" from "never incremented".
      See Also:
  • Method Details

    • increment

      public static long increment(String modelName)
      Advances the counter by one, together with the counter of the model the written type belongs to, and returns the new value.

      Never throws: a failure to advance is logged and reported as UNKNOWN_VERSION, so that a schema write is never failed by its own change-signalling. The cost of a missed increment is a projection rebuilding later than it could have, not incorrect data.

      Parameters:
      modelName - the model the written type belongs to, or null to advance the global counter alone
      Returns:
      the new version, or UNKNOWN_VERSION if it could not be advanced
    • getCurrentVersion

      public static long getCurrentVersion()
      Reads the current counter value without advancing it.

      Never throws: an unreadable counter is reported as UNKNOWN_VERSION, which a caller must treat as "cannot tell", not as "unchanged". A missing record means no schema write has ever been recorded, which is version zero.

      Returns:
      the current version, or UNKNOWN_VERSION if it could not be read
    • getCurrentVersionFast

      public static long getCurrentVersionFast()
      Returns the current version from its Redis copy, falling back to the database when the copy is absent and repopulating it.

      Exists because the version has to be consulted on every cached read in order to tell a current entry from a superseded one, and a database round trip per read would cost more than the cache saves. The database stays authoritative: Redis merely holds a copy.

      Returns:
      the current version, or UNKNOWN_VERSION if it cannot be determined