From 1060530236a25b09af2f164e425dea55d203d727 Mon Sep 17 00:00:00 2001 From: BijenderKumar1 Date: Sat, 11 May 2024 18:26:03 +0000 Subject: [PATCH 1/6] Resolve journal reset issue with orElse function definition --- core/shared/src/main/scala/zio/stm/ZSTM.scala | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/core/shared/src/main/scala/zio/stm/ZSTM.scala b/core/shared/src/main/scala/zio/stm/ZSTM.scala index 98747a5dbf4..68d78926190 100644 --- a/core/shared/src/main/scala/zio/stm/ZSTM.scala +++ b/core/shared/src/main/scala/zio/stm/ZSTM.scala @@ -1621,15 +1621,17 @@ object ZSTM { * Creates a function that can reset the journal. */ def prepareResetJournal(journal: Journal): () => Any = { - val saved = new MutableMap[TRef[_], Entry](journal.size) - - val it = journal.entrySet.iterator - while (it.hasNext) { - val entry = it.next - saved.put(entry.getKey, entry.getValue.copy()) + () => { + val saved = new MutableMap[TRef[_], Entry](journal.size) + val it = journal.entrySet.iterator + while (it.hasNext) { + val entry = it.next + saved.put(entry.getKey, entry.getValue.copy()) + } + journal.clear() + journal.putAll(saved) + () } - - () => { journal.clear(); journal.putAll(saved); () } } /** From a0454d03fc5226b35c6e5375b8093adfc0187b9e Mon Sep 17 00:00:00 2001 From: BijenderKumar1 Date: Sat, 11 May 2024 18:41:56 +0000 Subject: [PATCH 2/6] Remove extra braces --- core/shared/src/main/scala/zio/stm/ZSTM.scala | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/core/shared/src/main/scala/zio/stm/ZSTM.scala b/core/shared/src/main/scala/zio/stm/ZSTM.scala index 68d78926190..913c9870500 100644 --- a/core/shared/src/main/scala/zio/stm/ZSTM.scala +++ b/core/shared/src/main/scala/zio/stm/ZSTM.scala @@ -1620,18 +1620,16 @@ object ZSTM { /** * Creates a function that can reset the journal. */ - def prepareResetJournal(journal: Journal): () => Any = { - () => { - val saved = new MutableMap[TRef[_], Entry](journal.size) - val it = journal.entrySet.iterator - while (it.hasNext) { - val entry = it.next - saved.put(entry.getKey, entry.getValue.copy()) - } - journal.clear() - journal.putAll(saved) - () + def prepareResetJournal(journal: Journal): () => Any = () => { + val saved = new MutableMap[TRef[_], Entry](journal.size) + val it = journal.entrySet.iterator + while (it.hasNext) { + val entry = it.next + saved.put(entry.getKey, entry.getValue.copy()) } + journal.clear() + journal.putAll(saved) + () } /** From a13f843d4519f7b267913cf4e2b939e92b6b6c50 Mon Sep 17 00:00:00 2001 From: BijenderKumar1 Date: Sun, 12 May 2024 09:18:46 +0000 Subject: [PATCH 3/6] Resolve Formatting issues, CI Test Failures, and add a new test for LHS variable updates in orElse Test Suite --- .../src/test/scala/zio/stm/ZSTMSpec.scala | 18 ++++++++ core/shared/src/main/scala/zio/stm/ZSTM.scala | 45 +++++++++++++++---- 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/core-tests/shared/src/test/scala/zio/stm/ZSTMSpec.scala b/core-tests/shared/src/test/scala/zio/stm/ZSTMSpec.scala index b62128efc4d..6b758c438c7 100644 --- a/core-tests/shared/src/test/scala/zio/stm/ZSTMSpec.scala +++ b/core-tests/shared/src/test/scala/zio/stm/ZSTMSpec.scala @@ -873,6 +873,24 @@ object ZSTMSpec extends ZIOBaseSpec { val right = STM.fail("right") (left orElse right).commit.exit.map(assert(_)(fails(equalTo("right")))) + }, + test("retries on LHS variable change") { + for { + ref1 <- TRef.makeCommit(0) + ref2 <- TRef.makeCommit(0) + txn1 = ref1.get.flatMap { + case 0 => STM.retry + case n => STM.succeed(n) + } orElse ref2.get.flatMap { + case 0 => STM.retry + case n => STM.succeed(n) + } + txn2 = ref1.set(1) // if this is `ref2.set(1)`, it doesn't hang + fib <- txn1.commit.forkDaemon + _ <- liveClockSleep(1.second) + _ <- txn2.commit + result <- fib.join + } yield assert(result)(equalTo(1)) } ) @@ zioTag(errors), test("orElseEither returns result of the first successful transaction wrapped in either") { diff --git a/core/shared/src/main/scala/zio/stm/ZSTM.scala b/core/shared/src/main/scala/zio/stm/ZSTM.scala index 913c9870500..37a1be5f912 100644 --- a/core/shared/src/main/scala/zio/stm/ZSTM.scala +++ b/core/shared/src/main/scala/zio/stm/ZSTM.scala @@ -1620,16 +1620,31 @@ object ZSTM { /** * Creates a function that can reset the journal. */ - def prepareResetJournal(journal: Journal): () => Any = () => { - val saved = new MutableMap[TRef[_], Entry](journal.size) - val it = journal.entrySet.iterator - while (it.hasNext) { - val entry = it.next - saved.put(entry.getKey, entry.getValue.copy()) + def prepareResetJournal(journal: Journal): () => Any = { + val currentNewValues = new MutableMap[TRef[_], Any] + val itCapture = journal.entrySet.iterator + while (itCapture.hasNext) { + val entry = itCapture.next() + currentNewValues.put(entry.getKey, entry.getValue.unsafeGet[Any]) + } + + () => { + val saved = new MutableMap[TRef[_], Entry](journal.size) + val it = journal.entrySet.iterator + while (it.hasNext) { + val entry = it.next() + val key = entry.getKey + val resetValue = if (currentNewValues.containsKey(key)) { + currentNewValues.get(key) + } else { + entry.getValue.expected.value + } + saved.put(entry.getKey, entry.getValue.copy().reset(resetValue)) + } + journal.clear() + journal.putAll(saved) + () } - journal.clear() - journal.putAll(saved) - () } /** @@ -2051,6 +2066,18 @@ object ZSTM { _isChanged = self.isChanged } + /** + * Resets the Entry with a given value. + */ + def reset(resetValue: Any): Entry = new Entry { + type S = self.S + val tref = self.tref + val expected = self.expected + val isNew = self.isNew + var newValue = resetValue.asInstanceOf[S] + _isChanged = false + } + /** * Determines if the entry is invalid. This is the negated version of * `isValid`. From a16d5f1356d9819be10afaeffb4f4327343cf6a7 Mon Sep 17 00:00:00 2001 From: BijenderKumar1 Date: Thu, 16 May 2024 16:14:34 +0000 Subject: [PATCH 4/6] Make reset function private --- core/shared/src/main/scala/zio/stm/ZSTM.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/shared/src/main/scala/zio/stm/ZSTM.scala b/core/shared/src/main/scala/zio/stm/ZSTM.scala index 37a1be5f912..612f9b0c5b1 100644 --- a/core/shared/src/main/scala/zio/stm/ZSTM.scala +++ b/core/shared/src/main/scala/zio/stm/ZSTM.scala @@ -2069,7 +2069,7 @@ object ZSTM { /** * Resets the Entry with a given value. */ - def reset(resetValue: Any): Entry = new Entry { + private[stm] def reset(resetValue: Any): Entry = new Entry { type S = self.S val tref = self.tref val expected = self.expected From c78a23f63e26179d8ca82a3623424fb07a8ea778 Mon Sep 17 00:00:00 2001 From: BijenderKumar1 Date: Thu, 16 May 2024 16:18:16 +0000 Subject: [PATCH 5/6] Review unnecessary comment --- core-tests/shared/src/test/scala/zio/stm/ZSTMSpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-tests/shared/src/test/scala/zio/stm/ZSTMSpec.scala b/core-tests/shared/src/test/scala/zio/stm/ZSTMSpec.scala index 6b758c438c7..93c676cd619 100644 --- a/core-tests/shared/src/test/scala/zio/stm/ZSTMSpec.scala +++ b/core-tests/shared/src/test/scala/zio/stm/ZSTMSpec.scala @@ -885,7 +885,7 @@ object ZSTMSpec extends ZIOBaseSpec { case 0 => STM.retry case n => STM.succeed(n) } - txn2 = ref1.set(1) // if this is `ref2.set(1)`, it doesn't hang + txn2 = ref1.set(1) fib <- txn1.commit.forkDaemon _ <- liveClockSleep(1.second) _ <- txn2.commit From 839d1af38688c02673264118f19582b651fb9e9a Mon Sep 17 00:00:00 2001 From: BijenderKumar1 Date: Tue, 21 May 2024 12:34:42 +0000 Subject: [PATCH 6/6] Resolve linting errors --- core-tests/shared/src/test/scala/zio/stm/ZSTMSpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-tests/shared/src/test/scala/zio/stm/ZSTMSpec.scala b/core-tests/shared/src/test/scala/zio/stm/ZSTMSpec.scala index 93c676cd619..d33dbf9cd94 100644 --- a/core-tests/shared/src/test/scala/zio/stm/ZSTMSpec.scala +++ b/core-tests/shared/src/test/scala/zio/stm/ZSTMSpec.scala @@ -885,7 +885,7 @@ object ZSTMSpec extends ZIOBaseSpec { case 0 => STM.retry case n => STM.succeed(n) } - txn2 = ref1.set(1) + txn2 = ref1.set(1) fib <- txn1.commit.forkDaemon _ <- liveClockSleep(1.second) _ <- txn2.commit