Skip to content

Commit 019cbee

Browse files
Add ServiceDefinition to OperationContext (#36)
Add ServiceDefinition to OperationContext
1 parent c6a4139 commit 019cbee

File tree

3 files changed

+97
-11
lines changed

3 files changed

+97
-11
lines changed

nexus-sdk/src/main/java/io/nexusrpc/handler/OperationContext.java

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.nexusrpc.handler;
22

33
import io.nexusrpc.Link;
4+
import io.nexusrpc.ServiceDefinition;
45
import java.time.Instant;
56
import java.util.*;
67
import java.util.stream.Collectors;
@@ -23,20 +24,25 @@ public static Builder newBuilder(OperationContext context) {
2324
private final Map<String, String> headers;
2425
// This is not included in equals, hashCode, or toString
2526
private final @Nullable OperationMethodCanceller methodCanceller;
26-
private final List<Link> links = new ArrayList<>();
2727
private final Instant deadline;
28+
private final List<Link> links;
29+
private final @Nullable ServiceDefinition serviceDefinition;
2830

2931
private OperationContext(
3032
String service,
3133
String operation,
3234
Map<String, String> headers,
3335
@Nullable OperationMethodCanceller methodCanceller,
34-
Instant deadline) {
36+
Instant deadline,
37+
@Nullable ServiceDefinition serviceDefinition,
38+
List<Link> links) {
3539
this.service = service;
3640
this.operation = operation;
3741
this.headers = headers;
3842
this.methodCanceller = methodCanceller;
3943
this.deadline = deadline;
44+
this.serviceDefinition = serviceDefinition;
45+
this.links = links;
4046
}
4147

4248
/** Service name for the call. */
@@ -75,6 +81,11 @@ public boolean isMethodCancelled() {
7581
return methodCanceller == null ? null : methodCanceller.getCancellationReason();
7682
}
7783

84+
/** Get the service definition associated with this operation context, if any. */
85+
public @Nullable ServiceDefinition getServiceDefinition() {
86+
return serviceDefinition;
87+
}
88+
7889
/**
7990
* Get the deadline for the operation handler method. This is the time by which the method should
8091
* complete. This is not the operation's deadline.
@@ -136,18 +147,21 @@ public OperationContext removeMethodCancellationListener(
136147

137148
@Override
138149
public boolean equals(Object o) {
139-
if (this == o) return true;
140150
if (o == null || getClass() != o.getClass()) return false;
141151
OperationContext that = (OperationContext) o;
142152
return Objects.equals(service, that.service)
143153
&& Objects.equals(operation, that.operation)
144154
&& Objects.equals(headers, that.headers)
145-
&& Objects.equals(links, that.links);
155+
&& Objects.equals(methodCanceller, that.methodCanceller)
156+
&& Objects.equals(deadline, that.deadline)
157+
&& Objects.equals(links, that.links)
158+
&& Objects.equals(serviceDefinition, that.serviceDefinition);
146159
}
147160

148161
@Override
149162
public int hashCode() {
150-
return Objects.hash(service, operation, headers);
163+
return Objects.hash(
164+
service, operation, headers, methodCanceller, deadline, links, serviceDefinition);
151165
}
152166

153167
@Override
@@ -161,8 +175,14 @@ public String toString() {
161175
+ '\''
162176
+ ", headers="
163177
+ headers
178+
+ ", methodCanceller="
179+
+ methodCanceller
180+
+ ", deadline="
181+
+ deadline
164182
+ ", links="
165183
+ links
184+
+ ", serviceDefinition="
185+
+ serviceDefinition
166186
+ '}';
167187
}
168188

@@ -173,15 +193,25 @@ public static class Builder {
173193
private final SortedMap<String, String> headers;
174194
private @Nullable OperationMethodCanceller methodCanceller;
175195
private @Nullable Instant deadline;
196+
private @Nullable ServiceDefinition serviceDefinition;
197+
// Currently links are not set in the builder, but they need to be passed though to go from
198+
// OperationContext -> Builder
199+
// and back to OperationContext, so we keep them here.
200+
private final List<Link> links;
176201

177202
private Builder() {
178203
headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
204+
links = new ArrayList<>();
179205
}
180206

181207
private Builder(OperationContext context) {
182208
service = context.service;
183209
operation = context.operation;
184210
headers = new TreeMap<>(context.headers);
211+
methodCanceller = context.methodCanceller;
212+
deadline = context.deadline;
213+
serviceDefinition = context.serviceDefinition;
214+
links = context.links;
185215
}
186216

187217
/** Set service. Required. */
@@ -219,6 +249,12 @@ public Builder setDeadline(Instant deadline) {
219249
return this;
220250
}
221251

252+
/** Sets the service definition. */
253+
public Builder setServiceDefinition(ServiceDefinition serviceDefinition) {
254+
this.serviceDefinition = serviceDefinition;
255+
return this;
256+
}
257+
222258
/** Build the context. */
223259
public OperationContext build() {
224260
Objects.requireNonNull(service, "Service required");
@@ -236,7 +272,9 @@ public OperationContext build() {
236272
operation,
237273
Collections.unmodifiableMap(new TreeMap<>(normalizedHeaders)),
238274
methodCanceller,
239-
deadline);
275+
deadline,
276+
serviceDefinition,
277+
links);
240278
}
241279
}
242280
}

nexus-sdk/src/main/java/io/nexusrpc/handler/ServiceHandler.java

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,12 @@ public OperationStartResult<HandlerResultContent> startOperation(
6767
if (handler == null) {
6868
throw newUnrecognizedOperationException(context.getService(), context.getOperation());
6969
}
70+
// Populate the service definition in the context so that the handler can use it
71+
OperationContext contextWithServiceDef =
72+
OperationContext.newBuilder(context).setServiceDefinition(instance.getDefinition()).build();
73+
7074
OperationHandler<Object, Object> interceptedHandler =
71-
interceptOperationHandler(context, handler);
75+
interceptOperationHandler(contextWithServiceDef, handler);
7276
OperationDefinition definition =
7377
instance.getDefinition().getOperations().get(context.getOperation());
7478

@@ -84,7 +88,8 @@ public OperationStartResult<HandlerResultContent> startOperation(
8488
}
8589

8690
// Invoke handler
87-
OperationStartResult<?> result = interceptedHandler.start(context, details, inputObject);
91+
OperationStartResult<?> result =
92+
interceptedHandler.start(contextWithServiceDef, details, inputObject);
8893

8994
// If the result is an async result we can just return, but if it's a sync result we need to
9095
// serialize back out to bytes
@@ -108,7 +113,13 @@ public HandlerResultContent fetchOperationResult(
108113
if (handler == null) {
109114
throw newUnrecognizedOperationException(context.getService(), context.getOperation());
110115
}
111-
Object result = interceptOperationHandler(context, handler).fetchResult(context, details);
116+
// Populate the service definition in the context so that the handler can use it
117+
OperationContext contextWithServiceDef =
118+
OperationContext.newBuilder(context).setServiceDefinition(instance.getDefinition()).build();
119+
120+
Object result =
121+
interceptOperationHandler(contextWithServiceDef, handler)
122+
.fetchResult(contextWithServiceDef, details);
112123
return resultToContent(result);
113124
}
114125

@@ -136,7 +147,11 @@ public OperationInfo fetchOperationInfo(
136147
if (handler == null) {
137148
throw newUnrecognizedOperationException(context.getService(), context.getOperation());
138149
}
139-
return interceptOperationHandler(context, handler).fetchInfo(context, details);
150+
// Populate the service definition in the context so that the handler can use it
151+
OperationContext contextWithServiceDef =
152+
OperationContext.newBuilder(context).setServiceDefinition(instance.getDefinition()).build();
153+
return interceptOperationHandler(contextWithServiceDef, handler)
154+
.fetchInfo(contextWithServiceDef, details);
140155
}
141156

142157
@Override
@@ -150,7 +165,11 @@ public void cancelOperation(OperationContext context, OperationCancelDetails det
150165
if (handler == null) {
151166
throw newUnrecognizedOperationException(context.getService(), context.getOperation());
152167
}
153-
interceptOperationHandler(context, handler).cancel(context, details);
168+
// Populate the service definition in the context so that the handler can use it
169+
OperationContext contextWithServiceDef =
170+
OperationContext.newBuilder(context).setServiceDefinition(instance.getDefinition()).build();
171+
interceptOperationHandler(contextWithServiceDef, handler)
172+
.cancel(contextWithServiceDef, details);
154173
}
155174

156175
private static HandlerException newUnrecognizedOperationException(

nexus-sdk/src/test/java/io/nexusrpc/handler/OperationContextTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,23 @@
33
import static org.junit.jupiter.api.Assertions.assertEquals;
44

55
import io.nexusrpc.Link;
6+
import io.nexusrpc.example.TestServices;
67
import java.net.URI;
78
import java.net.URISyntaxException;
89
import java.time.Instant;
910
import java.util.Arrays;
1011
import org.junit.jupiter.api.Test;
1112

1213
public class OperationContextTest {
14+
15+
@ServiceImpl(service = TestServices.IntegerService.class)
16+
public class IntegerServiceImpl {
17+
@OperationImpl
18+
public OperationHandler<Integer, Integer> operation() {
19+
return OperationHandler.sync((ctx, details, input) -> 0);
20+
}
21+
}
22+
1323
@Test
1424
void linkTest() throws URISyntaxException {
1525
OperationContext octx =
@@ -34,4 +44,23 @@ void deadlineTest() {
3444
.build();
3545
assertEquals(deadline, octx.getDeadline());
3646
}
47+
48+
@Test
49+
void contextBuilderTest() throws URISyntaxException {
50+
OperationMethodCanceller omc = new OperationMethodCanceller();
51+
ServiceImplInstance serviceImpl = ServiceImplInstance.fromInstance(new IntegerServiceImpl());
52+
Instant deadline = Instant.now().plusMillis(1000);
53+
OperationContext octx =
54+
OperationContext.newBuilder()
55+
.setService("service")
56+
.setOperation("operation")
57+
.setDeadline(deadline)
58+
.putHeader("key", "value")
59+
.setMethodCanceller(omc)
60+
.setServiceDefinition(serviceImpl.getDefinition())
61+
.build();
62+
URI url = new URI("http://somepath?k=v");
63+
octx.setLinks(Link.newBuilder().setUri(url).setType("com.example.MyResource").build());
64+
assertEquals(octx, OperationContext.newBuilder(octx).build());
65+
}
3766
}

0 commit comments

Comments
 (0)