object IdempotentInsert

Utilities for safely and idempotently inserting records to a datastore.

Linear Supertypes
Ordering
  1. Alphabetic
  2. By Inheritance
Inherited
  1. IdempotentInsert
  2. AnyRef
  3. Any
  1. Hide All
  2. Show All
Visibility
  1. Public
  2. Protected

Value Members

  1. final def !=(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  2. final def ##: Int
    Definition Classes
    AnyRef → Any
  3. final def ==(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  4. final def asInstanceOf[T0]: T0
    Definition Classes
    Any
  5. def clone(): AnyRef
    Attributes
    protected[lang]
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.CloneNotSupportedException]) @native() @HotSpotIntrinsicCandidate()
  6. final def eq(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  7. def equals(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef → Any
  8. final def getClass(): Class[_ <: AnyRef]
    Definition Classes
    AnyRef → Any
    Annotations
    @native() @HotSpotIntrinsicCandidate()
  9. def hashCode(): Int
    Definition Classes
    AnyRef → Any
    Annotations
    @native() @HotSpotIntrinsicCandidate()
  10. def insertIgnoringConflicts(storage: DbStorage, oracleIgnoreIndex: String, insertBuilder: => SQLActionBuilder): WriteOnly[Int]

    Similar to insertVerifyingConflicts but without verifying that the existing data causing conflicts matches what we expect.

    Similar to insertVerifyingConflicts but without verifying that the existing data causing conflicts matches what we expect. Should only be use where the possibilities of conflicts is limited to retries of our insert.

  11. def insertVerifyingConflicts[A](storage: DbStorage, oracleIgnoreIndex: String, insertBuilder: => SQLActionBuilder, select: ReadOnly[A], expectedRowsInserted: Int = 1)(existingCondition: (A) => Boolean, errorMessage: (A) => String)(implicit loggingContext: ErrorLoggingContext, executionContext: ExecutionContext): All[Unit]

    Execute an insert to an append-only store.

    Execute an insert to an append-only store. If less than expectedRowsInserted are found inserted perform a select and verify that the existing data is what we expect to existing in our store. If the existing data fails the provided check predicate a java.lang.IllegalStateException will be thrown as this indicates either a bug or a configuration error (such as a new node running with a database initialized by another node). If more rows are returned than expectedRowsInserted a java.lang.IllegalStateException is also thrown as this indicates the insert query is doing something contrary to the developers expectations and is likely a bug.

    To use safely use the oracleIgnoreIndex field it **must** be suitable for directly interpolating as a raw string into the query without causing any risk of SQL injection. It is recommended that this value should be hard coded and never come from a value based on the environment or user input.

    This method will generate the insert into prefix for the insert statement, so insertBuilder needs to only contain the body of the insert statement excluding the typical insert into prefix (this is so for oracle we can generate a suitable IGNORE_ROW_ON_DUPKEY_INDEX hint.

    Typical usage will look like:

    insertVerifyingConflicts(
      logger,
      storage,
      "my_table ( pk_col )", // callers MUST ensure this is safe to interpolate directly into the sql query
      sql"my_table (pk_col, name) values ($$id, $$name)", // note the missing `insert into` prefix or any `on conflict` postfix. this will be generated appropriately for the target db.
      sql"select name from my_table where pk_col = $$id".as[String].head // query values to check successfully exist in the target store.
    )(
      _ == name,
      existingName => s"Expected row $$id to have name $$name but found existing name $$existingName"
    )

    Note that no transaction is started within this method and therefore changes could become visible between the insert and the select that we may then perform. However as the usage of this is intended for append-only stores separate modifications of this data is not expected.

    Regarding performance the select statement will only be executed if the returned inserted row count is different from the expectedRowsInserted value. We anticipate this happening potentially due to crashes or retries due to connectivity issues, and should be rare during normal healthy operation. So typically only the insert should be run.

  12. final def isInstanceOf[T0]: Boolean
    Definition Classes
    Any
  13. final def ne(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  14. final def notify(): Unit
    Definition Classes
    AnyRef
    Annotations
    @native() @HotSpotIntrinsicCandidate()
  15. final def notifyAll(): Unit
    Definition Classes
    AnyRef
    Annotations
    @native() @HotSpotIntrinsicCandidate()
  16. final def synchronized[T0](arg0: => T0): T0
    Definition Classes
    AnyRef
  17. def toString(): String
    Definition Classes
    AnyRef → Any
  18. final def wait(arg0: Long, arg1: Int): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.InterruptedException])
  19. final def wait(arg0: Long): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.InterruptedException]) @native()
  20. final def wait(): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.InterruptedException])

Deprecated Value Members

  1. def finalize(): Unit
    Attributes
    protected[lang]
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.Throwable]) @Deprecated
    Deprecated

Inherited from AnyRef

Inherited from Any

Ungrouped