Skip to content

Commit

Permalink
XD-1112 make read-only transaction freeze the session
Browse files Browse the repository at this point in the history
  • Loading branch information
kirillvasilenko committed Sep 10, 2024
1 parent 9b9fedf commit a1d0486
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,16 @@ class OStoreTransactionImpl(
check(session.isActiveOnCurrentThread) { "The session is not active on the current thread" }
check(session.transaction is OTransactionNoTx) { "The session must not have a transaction" }
try {
if (readOnly) {
/**
* It is not enough to provide the best experience to the client code.
* The session will throw an exception only on commit(), but not when
* the client code creates/edits/deletes entities.
*
* So, we keep and check the readOnly flag too.
*/
session.freeze(true)
}
session.begin()
// initialize transaction id
transactionIdImpl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package jetbrains.exodus.entitystore.orientdb

import com.orientechnologies.common.concur.lock.OModificationOperationProhibitedException
import com.orientechnologies.orient.core.db.ODatabaseSession
import com.orientechnologies.orient.core.metadata.schema.OClass
import com.orientechnologies.orient.core.metadata.schema.OType
import com.orientechnologies.orient.core.record.OVertex
Expand Down Expand Up @@ -57,7 +59,6 @@ class OStoreTransactionLifecycleTest : OTestMixin {

@Test
fun `commit() and abort() finish transaction`() {
orientDb.store.executeInTransaction { }
commitAbort.forEach { (terminalTxActionName, terminalTxAction) ->
allTxActions.forEach { (txActionName, txAction) ->
val tx = beginTransaction()
Expand Down Expand Up @@ -118,4 +119,16 @@ class OStoreTransactionLifecycleTest : OTestMixin {
}
}
}

@Test
fun `read-only transaction freezes the session`() {
beginReadonlyTransaction()
val session = ODatabaseSession.getActiveSession() as ODatabaseSession

val v = session.newVertex()
v.save<OVertex>()
assertFailsWith<OModificationOperationProhibitedException> { session.commit() }

session.close()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package jetbrains.exodus.entitystore.orientdb

import com.orientechnologies.common.concur.lock.OModificationOperationProhibitedException
import com.orientechnologies.orient.core.db.ODatabase.STATUS
import com.orientechnologies.orient.core.exception.ODatabaseException
import com.orientechnologies.orient.core.metadata.schema.OClass
Expand All @@ -38,6 +39,31 @@ class OTransactionLifecycleTest : OTestMixin {

override val orientDb = orientDbRule

@Test
fun `session-freeze(true) makes the session read-only`() {
val session = orientDb.openSession()

session.freeze(true)

val v = session.newVertex()
assertFailsWith<OModificationOperationProhibitedException> { v.save<OVertex>() }

session.begin()
val v1 = session.newVertex()
v1.save<OVertex>()
assertFailsWith<OModificationOperationProhibitedException> { session.commit() }

// after release() we can write again
session.release()

session.begin()
val v2 = session.newVertex()
v2.save<OVertex>()
session.commit()

session.close()
}

@Test
fun `open, begin, commit, close - no changes`() {
val session = orientDb.openSession()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ interface OTestMixin {
return store.beginTransaction() as OStoreTransactionImpl
}

fun beginReadonlyTransaction(): OStoreTransactionImpl {
val store = orientDb.store
return store.beginReadonlyTransaction() as OStoreTransactionImpl
}

fun <R> withStoreTx(block: (OStoreTransaction) -> R): R {
return orientDb.withStoreTx(block)
}
Expand Down

0 comments on commit a1d0486

Please sign in to comment.