22
33import static org .junit .Assume .assumeTrue ;
44
5- import io .nexusrpc .OperationException ;
6- import io .nexusrpc .handler .OperationCancelDetails ;
7- import io .nexusrpc .handler .OperationContext ;
8- import io .nexusrpc .handler .OperationHandler ;
9- import io .nexusrpc .handler .OperationImpl ;
10- import io .nexusrpc .handler .OperationStartDetails ;
11- import io .nexusrpc .handler .OperationStartResult ;
12- import io .nexusrpc .handler .ServiceImpl ;
135import io .temporal .api .nexus .v1 .Endpoint ;
146import io .temporal .client .NexusClient ;
157import io .temporal .client .NexusOperationException ;
2012import io .temporal .client .UntypedNexusOperationHandle ;
2113import io .temporal .client .UntypedNexusServiceClient ;
2214import io .temporal .testing .internal .SDKTestWorkflowRule ;
15+ import io .temporal .workflow .shared .EchoNexusServiceImpl ;
2316import io .temporal .workflow .shared .TestNexusServices ;
2417import io .temporal .workflow .shared .TestWorkflows ;
2518import java .time .Duration ;
2619import java .util .UUID ;
27- import java .util .concurrent .atomic .AtomicInteger ;
2820import org .junit .Assert ;
2921import org .junit .BeforeClass ;
3022import org .junit .Rule ;
@@ -41,7 +33,7 @@ public class NexusOperationHandleTest {
4133 public SDKTestWorkflowRule testWorkflowRule =
4234 SDKTestWorkflowRule .newBuilder ()
4335 .setWorkflowTypes (PlaceholderWorkflowImpl .class )
44- .setNexusServiceImplementation (new TestNexusServiceImpl ())
36+ .setNexusServiceImplementation (new EchoNexusServiceImpl ())
4537 .build ();
4638
4739 @ BeforeClass
@@ -83,21 +75,21 @@ public void describeWithoutRunIdTargetsLatest() {
8375 // invokations the test server received to make sure it increments.
8476 @ Test
8577 public void cancelSucceedsForStartedOperation () {
86- int before = TestNexusServiceImpl .cancelInvocations .get ();
78+ int before = EchoNexusServiceImpl .cancelInvocations .get ();
8779 startPendingOperation ().cancel ();
8880 assertCancelDelivered (before );
8981 }
9082
9183 @ Test
9284 public void cancelWithReasonSucceedsForStartedOperation () {
93- int before = TestNexusServiceImpl .cancelInvocations .get ();
85+ int before = EchoNexusServiceImpl .cancelInvocations .get ();
9486 startPendingOperation ().cancel ("test-cancel-reason" );
9587 assertCancelDelivered (before );
9688 }
9789
9890 @ Test
9991 public void cancelWithNullReasonSucceeds () {
100- int before = TestNexusServiceImpl .cancelInvocations .get ();
92+ int before = EchoNexusServiceImpl .cancelInvocations .get ();
10193 startPendingOperation ().cancel (null );
10294 assertCancelDelivered (before );
10395 }
@@ -109,7 +101,7 @@ public void cancelWithNullReasonSucceeds() {
109101 */
110102 private static void assertCancelDelivered (int countBeforeCancel ) {
111103 long deadlineNanos = System .nanoTime () + Duration .ofSeconds (8 ).toNanos ();
112- while (TestNexusServiceImpl .cancelInvocations .get () <= countBeforeCancel
104+ while (EchoNexusServiceImpl .cancelInvocations .get () <= countBeforeCancel
113105 && System .nanoTime () < deadlineNanos ) {
114106 try {
115107 Thread .sleep (100 );
@@ -120,7 +112,7 @@ private static void assertCancelDelivered(int countBeforeCancel) {
120112 }
121113 Assert .assertTrue (
122114 "cancel RPC was not delivered to the handler within the poll budget" ,
123- TestNexusServiceImpl .cancelInvocations .get () > countBeforeCancel );
115+ EchoNexusServiceImpl .cancelInvocations .get () > countBeforeCancel );
124116 }
125117
126118 @ Test
@@ -149,7 +141,7 @@ public void terminateWithNullReasonSucceeds() {
149141 * the lifecycle RPCs have a non-terminal operation to act on.
150142 */
151143 private UntypedNexusOperationHandle startPendingOperation () {
152- return startOperation (TestNexusServiceImpl .ASYNC_PREFIX + UUID .randomUUID ());
144+ return startOperation (EchoNexusServiceImpl .ASYNC_PREFIX + UUID .randomUUID ());
153145 }
154146
155147 /**
@@ -227,61 +219,9 @@ public String execute(String input) {
227219 }
228220 }
229221
230- @ ServiceImpl (service = TestNexusServices .TestNexusService1 .class )
231- public static class TestNexusServiceImpl {
232- /** Inputs starting with this prefix make the handler throw, exercising the failure path. */
233- static final String FAIL_PREFIX = "FAIL:" ;
234-
235- /**
236- * Inputs starting with this prefix make the handler return an async-started result without ever
237- * completing the operation. Used by cancel/terminate tests so the operation stays in RUNNING
238- * state long enough for the lifecycle RPC to be observed.
239- */
240- static final String ASYNC_PREFIX = "ASYNC:" ;
241-
242- /**
243- * Incremented every time the worker invokes the handler's {@code cancel(...)} callback. The
244- * cancel tests poll this counter to verify the cancel RPC was delivered end-to-end (client →
245- * server → worker), even though the no-op cancel doesn't drive the operation to a terminal
246- * state.
247- */
248- static final AtomicInteger cancelInvocations = new AtomicInteger ();
249-
250- @ OperationImpl
251- public OperationHandler <String , String > operation () {
252- return new OperationHandler <String , String >() {
253- @ Override
254- public OperationStartResult <String > start (
255- OperationContext context , OperationStartDetails details , String input )
256- throws OperationException {
257- if (input != null && input .startsWith (FAIL_PREFIX )) {
258- // OperationException.failed = definitive failure (no retries) so the caller's
259- // getResult surfaces the failure instead of timing out.
260- throw OperationException .failed ("intentional failure: " + input );
261- }
262- if (input != null && input .startsWith (ASYNC_PREFIX )) {
263- // Async-started: server keeps the operation in RUNNING state until something
264- // external (terminate, cancellation that takes effect, or schedule-to-close)
265- // transitions it. Terminate is server-forced so it transitions reliably; cancel is
266- // cooperative and won't transition without a backing entity.
267- return OperationStartResult .async ("token-" + UUID .randomUUID ());
268- }
269- return OperationStartResult .sync ("echo:" + (input == null ? "<null>" : input ));
270- }
271-
272- @ Override
273- public void cancel (OperationContext context , OperationCancelDetails details ) {
274- // Record delivery for the cancel tests; otherwise a no-op. Driving the operation to a
275- // terminal CANCELED state would require a backing entity (e.g. a workflow).
276- cancelInvocations .incrementAndGet ();
277- }
278- };
279- }
280- }
281-
282222 @ Test
283223 public void getResultPropagatesOperationFailure () {
284- UntypedNexusOperationHandle handle = startOperation (TestNexusServiceImpl .FAIL_PREFIX + "boom" );
224+ UntypedNexusOperationHandle handle = startOperation (EchoNexusServiceImpl .FAIL_PREFIX + "boom" );
285225 String operationId = handle .getNexusOperationId ();
286226
287227 try {
0 commit comments