This is an automated email from the ASF dual-hosted git repository.

dcapwell pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra-accord.git


The following commit(s) were added to refs/heads/trunk by this push:
     new f6b0a699 Updated so txn.execute is always called before txn.result, 
which enables Cassandra to pass around rejections found while creating the 
mutations.
f6b0a699 is described below

commit f6b0a6998faca767e6951976097dec704c306b0e
Author: David Capwell <[email protected]>
AuthorDate: Thu Dec 11 09:31:20 2025 -0800

    Updated so txn.execute is always called before txn.result, which enables 
Cassandra to pass around rejections found while creating the mutations.
    
    patch by David Capwell; reviewed by Benedict Elliott Smith, Caleb 
Rackliffe, Jyothsna Konisa for CASSANDRA-21061
---
 .../main/java/accord/coordinate/ExecuteTxn.java    |  7 ++---
 .../src/main/java/accord/utils/RandomSource.java   |  8 +++++
 accord-core/src/test/java/accord/utils/Gens.java   |  3 ++
 .../src/test/java/accord/utils/Property.java       | 36 +++++++++++++++-------
 gradle.properties                                  |  4 +++
 gradle/wrapper/gradle-wrapper.properties           |  3 +-
 6 files changed, 45 insertions(+), 16 deletions(-)

diff --git a/accord-core/src/main/java/accord/coordinate/ExecuteTxn.java 
b/accord-core/src/main/java/accord/coordinate/ExecuteTxn.java
index 3c1e2a52..5b06000a 100644
--- a/accord-core/src/main/java/accord/coordinate/ExecuteTxn.java
+++ b/accord-core/src/main/java/accord/coordinate/ExecuteTxn.java
@@ -391,11 +391,10 @@ public class ExecuteTxn extends ReadCoordinator<Result, 
ReadReply>
                 executeAt = new TimestampWithUniqueHlc(executeAt, uniqueHlc);
             }
 
-            // Always compute Result before Write to provide integrations with 
a predictable invocation order
-            // in case there is shared state between Result and Update. This 
can change if really needed
-            // just make sure to check the integrations to make sure it won't 
break anything
-            Result result = txn.result(txnId, executeAt, data);
+            // Always compute Writes before Result to provide integrations 
with a predictable invocation order
+            // in case there is shared state between Result and Update.
             Writes writes = txnId.is(Txn.Kind.Write) ? txn.execute(txnId, 
executeAt, data) : null;
+            Result result = txn.result(txnId, executeAt, data);
             adapter().persist(node, executor, allTopologies, route, ballot, 
flags, txnId, txn, executeAt, stableDeps, writes, result, takeCallback());
         }
         else
diff --git a/accord-core/src/main/java/accord/utils/RandomSource.java 
b/accord-core/src/main/java/accord/utils/RandomSource.java
index 80b3cd2f..c3decc5e 100644
--- a/accord-core/src/main/java/accord/utils/RandomSource.java
+++ b/accord-core/src/main/java/accord/utils/RandomSource.java
@@ -292,24 +292,32 @@ public interface RandomSource
 
     default <T> T pickOrderedSet(SortedSet<T> set)
     {
+        Invariants.require(!set.isEmpty(), "can not pick from an empty 
collection");
+        if (set.size() == 1) return Iterables.getFirst(set, null);
         int offset = nextInt(0, set.size());
         return Iterables.get(set, offset);
     }
 
     default <T> T pickOrderedSet(LinkedHashSet<T> set)
     {
+        Invariants.require(!set.isEmpty(), "can not pick from an empty 
collection");
+        if (set.size() == 1) return Iterables.getFirst(set, null);
         int offset = nextInt(0, set.size());
         return Iterables.get(set, offset);
     }
 
     default <T extends Enum<T>> T pickOrderedSet(EnumSet<T> set)
     {
+        Invariants.require(!set.isEmpty(), "can not pick from an empty 
collection");
+        if (set.size() == 1) return Iterables.getFirst(set, null);
         int offset = nextInt(0, set.size());
         return Iterables.get(set, offset);
     }
 
     default <T extends Comparable<? super T>> T pickUnorderedSet(Set<T> set)
     {
+        Invariants.require(!set.isEmpty(), "can not pick from an empty 
collection");
+        if (set.size() == 1) return Iterables.getFirst(set, null);
         if (set instanceof SortedSet)
             return pickOrderedSet((SortedSet<T>) set);
         List<T> values = new ArrayList<>(set);
diff --git a/accord-core/src/test/java/accord/utils/Gens.java 
b/accord-core/src/test/java/accord/utils/Gens.java
index c310fb6b..5af02308 100644
--- a/accord-core/src/test/java/accord/utils/Gens.java
+++ b/accord-core/src/test/java/accord/utils/Gens.java
@@ -862,6 +862,9 @@ public class Gens
      */
     public static <T> Gen<Gen<T>> mixedDistribution(List<T> list)
     {
+        Invariants.require(!list.isEmpty(), "can not pick from an empty 
collection");
+        if (list.size() == 1)
+            return i -> constant(list.get(0));
         return rs -> {
             switch (rs.nextInt(0, 4))
             {
diff --git a/accord-core/src/test/java/accord/utils/Property.java 
b/accord-core/src/test/java/accord/utils/Property.java
index 92faad08..0bd40f44 100644
--- a/accord-core/src/test/java/accord/utils/Property.java
+++ b/accord-core/src/test/java/accord/utils/Property.java
@@ -72,6 +72,11 @@ public class Property
         }
 
         @SuppressWarnings("unchecked")
+        public T withOnlySeed(long seed)
+        {
+            return withSeed(seed).withExamples(1);
+        }
+
         public T withExamples(int examples)
         {
             if (examples <= 0)
@@ -104,7 +109,7 @@ public class Property
             }
             catch (ExecutionException e)
             {
-                throw new PropertyError(propertyError(this, e.getCause()));
+                throw new PropertyError(propertyError(this, e.getCause()), 
e.getCause());
             }
             catch (InterruptedException e)
             {
@@ -213,10 +218,11 @@ public class Property
         return sb.toString();
     }
 
-    private static String statefulPropertyError(StatefulBuilder input, 
Throwable cause, Object state, List<String> history)
+    private static String statefulPropertyError(StatefulBuilder input, 
Throwable cause, Object state, int failingStep, List<String> history)
     {
         StringBuilder sb = propertyErrorCommon(input, cause);
         sb.append("Steps: ").append(input.steps).append('\n');
+        sb.append("Failing Step: ").append(failingStep).append('\n');
         sb.append("Values:\n");
         String stateStr = state == null ? null : 
state.toString().replace("\n", "\n\t\t");
         sb.append("\tState: ").append(stateStr).append(": ").append(state == 
null ? "unknown type" : state.getClass().getCanonicalName()).append('\n');
@@ -493,6 +499,7 @@ public class Property
             {
                 State state = null;
                 List<String> history = new ArrayList<>(steps);
+                int seenCommands = 0;
                 LongArrayList historyTiming = stepTimeout == null ? null : new 
LongArrayList();
                 try
                 {
@@ -506,7 +513,7 @@ public class Property
                         for (int j = 0; j < steps; j++)
                         {
                             Gen<Command<State, SystemUnderTest, ?>> cmdGen = 
commands.commands(state);
-                            Command cmd = cmdGen.next(rs);
+                            Command<State, SystemUnderTest, ?> cmd = 
cmdGen.next(rs);
                             for (int a = 0; cmd.checkPreconditions(state) != 
PreCheckResult.Ok && a < 42; a++)
                             {
                                 if (a == 41)
@@ -517,14 +524,16 @@ public class Property
                             {
                                 for (Command<State, SystemUnderTest, ?> sub : 
((MultistepCommand<State, SystemUnderTest>) cmd))
                                 {
+                                    seenCommands++;
                                     history.add(sub.detailed(state));
-                                    process(sub, state, sut, history.size(), 
historyTiming);
+                                    process(sub, state, sut, seenCommands, 
historyTiming);
                                 }
                             }
                             else
                             {
+                                seenCommands++;
                                 history.add(cmd.detailed(state));
-                                process(cmd, state, sut, history.size(), 
historyTiming);
+                                process(cmd, state, sut, seenCommands, 
historyTiming);
                             }
                         }
                         commands.destroySut(sut, null);
@@ -542,7 +551,7 @@ public class Property
                 }
                 catch (Throwable t)
                 {
-                    throw new PropertyError(statefulPropertyError(this, t, 
state, maybeRewriteHistory(history, historyTiming)), t);
+                    throw new PropertyError(statefulPropertyError(this, t, 
state, seenCommands, maybeRewriteHistory(history, historyTiming)), t);
                 }
                 if (pure)
                 {
@@ -577,8 +586,7 @@ public class Property
             return newHistory;
         }
 
-        @SuppressWarnings({ "rawtypes", "unchecked" })
-        private <State, SystemUnderTest> void process(Command cmd, State 
state, SystemUnderTest sut, int id, @Nullable LongArrayList stepTiming) throws 
Throwable
+        private <State, SystemUnderTest> void process(Command<State, 
SystemUnderTest, ?> cmd, State state, SystemUnderTest sut, int id, @Nullable 
LongArrayList stepTiming) throws Throwable
         {
             if (stepTimeout == null)
             {
@@ -609,8 +617,10 @@ public class Property
         default String detailed(State state) {return this.toString();}
         default void process(State state, SystemUnderTest sut) throws Throwable
         {
-            checkPostconditions(state, apply(state),
-                                sut, run(sut));
+            Result apply = apply(state);
+            Result run = run(sut);
+            checkPostconditions(state, apply,
+                                sut, run);
         }
     }
 
@@ -851,6 +861,7 @@ public class Property
         default void destroyState(State state, @Nullable Throwable cause) 
throws Throwable {}
         default void destroySut(SystemUnderTest sut, @Nullable Throwable 
cause) throws Throwable {}
         Gen<Command<State, SystemUnderTest, ?>> commands(State state) throws 
Throwable;
+
     }
 
     public static <State, SystemUnderTest> CommandsBuilder<State, 
SystemUnderTest> commands(Supplier<Gen<State>> stateGen, Function<State, 
SystemUnderTest> sutFactory)
@@ -907,6 +918,7 @@ public class Property
             this.sutFactory = sutFactory;
         }
 
+
         public CommandsBuilder<State, SystemUnderTest> 
preCommands(FailingConsumer<State> preCommands)
         {
             this.preCommands = preCommands;
@@ -1126,7 +1138,7 @@ public class Property
                                 for (Setup<State, SystemUnderTest> s : 
unknownWeights)
                                     weights.put(s, 
unknownWeightGen.nextInt(rs));
                             }
-                            nonConditional = Gens.pick(weights);
+                            nonConditional = weights.isEmpty() ? null : 
Gens.pick(weights);
                             if (conditionalCommands != null)
                             {
                                 conditionalWeights = new LinkedHashMap<>();
@@ -1233,6 +1245,7 @@ public class Property
                     for (var fn : onFailures)
                         fn.onFailure(state, sut, history, cause);
                 }
+
             };
         }
 
@@ -1251,4 +1264,5 @@ public class Property
             void accept(A a, B b) throws Throwable;
         }
     }
+
 }
diff --git a/gradle.properties b/gradle.properties
index fa64f1f6..6057f461 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -17,3 +17,7 @@
 accord_group=accord
 accord_artifactId=accord
 accord_version=1.0-SNAPSHOT
+
+# Some times there are ephemeral issues with fetching dependencies (namely 
Rat) in CI, so this bumps the timeout to 120s to try to make it more stable
+systemProp.org.gradle.internal.http.connectionTimeout=120000
+systemProp.org.gradle.internal.http.socketTimeout=120000
diff --git a/gradle/wrapper/gradle-wrapper.properties 
b/gradle/wrapper/gradle-wrapper.properties
index 72371299..8a9c3cdf 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -17,6 +17,7 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
-networkTimeout=10000
+# Some CI environments have ephemeral issues fetching the gradle runtime, so 
increased the timeout from the default 10s to 60s to make it more stable
+networkTimeout=60000
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to