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

jvmMain.DefaultTransaction.kt Maven / Gradle / Ivy

The newest version!
package io.fluidsonic.raptor.transactions


internal class DefaultTransaction(
	override val context: DefaultTransactionContext,
	private val observers: List,
) : RaptorTransaction {

	private var state = State.created


	override suspend fun fail(error: Throwable) {
		when (state) {
			State.created -> error("Cannot fail a transaction that has not yet started.")
			State.failed -> error("Cannot fail a transaction that has already failed.")
			State.started -> {
				val observerCount = observers.size
				var index = observerCount - 1

				while (index >= 0) {
					val observer = observers[index]
					try {
						observer.onFail(context, error)
					}
					catch (e: Throwable) {
						error.addSuppressed(e)
					}

					index -= 1
				}

				state = State.failed
			}

			State.stopped -> error("Cannot fail a transaction that has already stopped.")
		}
	}


	override suspend fun start() {
		when (state) {
			State.created -> {
				var index = 0
				val observerCount = observers.size
				var error: Throwable? = null

				while (index < observerCount) {
					val observer = observers[index]
					try {
						observer.onStart(context)
						index += 1
					}
					catch (e: Throwable) {
						error = e
						break
					}
				}

				when (error) {
					null -> state = State.started
					else -> {
						while (index > 0) {
							index -= 1

							val observer = observers[index]
							try {
								observer.onFail(context, error)
							}
							catch (e: Throwable) {
								error.addSuppressed(e)
							}
						}

						state = State.failed
						throw error
					}
				}
			}

			State.failed -> error("Cannot start a transaction that has failed.")
			State.started -> error("Cannot start a transaction that has already started.")
			State.stopped -> error("Cannot start a transaction that has already stopped.")
		}
	}


	override suspend fun stop() {
		when (state) {
			State.created -> error("Cannot stop a transaction that has not yet started.")
			State.failed -> error("Cannot stop a transaction that has failed.")
			State.started -> {
				val observerCount = observers.size
				var index = observerCount - 1
				var error: Throwable? = null

				while (index >= 0) {
					val observer = observers[index]
					try {
						observer.onStop(context)
						index -= 1
					}
					catch (e: Throwable) {
						error = e
						break
					}
				}

				when (error) {
					null -> state = State.stopped
					else -> {
						while (index > 0) {
							index -= 1

							val observer = observers[index]
							try {
								observer.onFail(context, error)
							}
							catch (e: Throwable) {
								error.addSuppressed(e)
							}
						}

						state = State.failed
						throw error
					}
				}
			}

			State.stopped -> error("Cannot stop a transaction that has already stopped.")
		}
	}


	private enum class State {

		created,
		failed,
		started,
		stopped,
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy