3
3
import com .eventstore .dbclient .proto .shared .Shared ;
4
4
import com .eventstore .dbclient .proto .streams .StreamsGrpc ;
5
5
import com .eventstore .dbclient .proto .streams .StreamsOuterClass ;
6
- import io .grpc .Metadata ;
7
- import io .grpc .Status ;
8
- import io .grpc .StatusRuntimeException ;
9
- import io .grpc .stub .ClientCallStreamObserver ;
10
- import io .grpc .stub .ClientResponseObserver ;
11
- import org .slf4j .Logger ;
12
- import org .slf4j .LoggerFactory ;
13
6
14
- import javax .validation .constraints .NotNull ;
15
7
import java .util .concurrent .CompletableFuture ;
16
8
17
9
abstract class AbstractRegularSubscription {
18
- private static Logger logger = LoggerFactory .getLogger (AbstractRegularSubscription .class );
19
10
protected static final StreamsOuterClass .ReadReq .Options .Builder defaultReadOptions ;
20
11
protected static final StreamsOuterClass .ReadReq .Options .Builder defaultSubscribeOptions ;
21
12
22
13
protected SubscriptionListener listener ;
23
14
protected Checkpointer checkpointer = null ;
24
15
private final GrpcClient client ;
25
- private final OptionsBase <?> options ;
16
+ private final OptionsWithBackPressure <?> options ;
26
17
27
- protected AbstractRegularSubscription (GrpcClient client , OptionsBase <?> options ) {
18
+ protected AbstractRegularSubscription (GrpcClient client , OptionsWithBackPressure <?> options ) {
28
19
this .client = client ;
29
20
this .options = options ;
30
21
}
@@ -40,120 +31,40 @@ protected AbstractRegularSubscription(GrpcClient client, OptionsBase<?> options)
40
31
41
32
protected abstract StreamsOuterClass .ReadReq .Options .Builder createOptions ();
42
33
43
- @ SuppressWarnings ("unchecked" )
44
34
public CompletableFuture <Subscription > execute () {
45
- return this .client .run (channel -> {
46
- StreamsOuterClass .ReadReq readReq = StreamsOuterClass .ReadReq .newBuilder ()
47
- .setOptions (createOptions ())
48
- .build ();
49
-
50
- StreamsGrpc .StreamsStub streamsClient = GrpcUtils .configureStub (StreamsGrpc .newStub (channel ), this .client .getSettings (), this .options );
51
-
52
- CompletableFuture <Subscription > future = new CompletableFuture <>();
53
- ClientResponseObserver <StreamsOuterClass .ReadReq , StreamsOuterClass .ReadResp > observer = new ClientResponseObserver <StreamsOuterClass .ReadReq , StreamsOuterClass .ReadResp >() {
54
- private boolean _confirmed ;
55
- private Subscription _subscription ;
56
- private ClientCallStreamObserver <StreamsOuterClass .ReadReq > _requestStream ;
57
-
58
- @ Override
59
- public void beforeStart (ClientCallStreamObserver <StreamsOuterClass .ReadReq > requestStream ) {
60
- this ._requestStream = requestStream ;
61
- }
62
-
63
- @ Override
64
- public void onNext (@ NotNull StreamsOuterClass .ReadResp readResp ) {
65
- if (!_confirmed && readResp .hasConfirmation ()) {
66
- this ._confirmed = true ;
67
- this ._subscription = new Subscription (this ._requestStream ,
68
- readResp .getConfirmation ().getSubscriptionId (), checkpointer );
69
- future .complete (this ._subscription );
70
- listener .onConfirmation (this ._subscription );
71
- return ;
72
- }
73
-
74
- if (!_confirmed && readResp .hasEvent ()) {
75
- onError (new IllegalStateException ("Unconfirmed subscription received event" ));
76
- return ;
77
- }
78
-
79
- if (_confirmed && readResp .hasCheckpoint ()) {
80
- Checkpointer checkpointer = this ._subscription .getCheckpointer ();
81
- if (checkpointer == null ) {
82
- return ;
83
- }
84
-
85
- StreamsOuterClass .ReadResp .Checkpoint checkpoint = readResp .getCheckpoint ();
86
- Position checkpointPos = new Position (checkpoint .getCommitPosition (), checkpoint .getPreparePosition ());
87
- checkpointer .onCheckpoint (this ._subscription , checkpointPos );
88
- return ;
89
- }
90
-
91
- if (_confirmed && readResp .hasCaughtUp ()) {
92
- listener .onCaughtUp (_subscription );
93
- return ;
94
- }
95
-
96
- if (_confirmed && readResp .hasFellBehind ()) {
97
- listener .onFellBehind (_subscription );
98
- return ;
99
- }
35
+ CompletableFuture <Subscription > future = new CompletableFuture <>();
100
36
101
- if (_confirmed && !readResp .hasEvent ()) {
102
- logger .warn (
103
- String .format ("Confirmed subscription %s received non-{event,checkpoint} variant" ,
104
- _subscription .getSubscriptionId ()));
105
- return ;
106
- }
37
+ this .client .getWorkItemArgs ().whenComplete ((args , error ) -> {
38
+ if (error != null ) {
39
+ future .completeExceptionally (error );
40
+ return ;
41
+ }
107
42
108
- try {
109
- ResolvedEvent resolvedEvent = ResolvedEvent .fromWire (readResp .getEvent ());
110
- ClientTelemetry .traceSubscribe (
111
- () -> listener .onEvent (this ._subscription , resolvedEvent ),
112
- _subscription .getSubscriptionId (),
113
- channel ,
114
- client .getSettings (),
115
- options .getCredentials (),
116
- resolvedEvent .getEvent ());
117
- } catch (Exception e ) {
118
- onError (e );
119
- }
120
- }
43
+ ReadResponseObserver observer = createObserver (args , future );
44
+ observer .onConnected (args );
121
45
122
- @ Override
123
- public void onError (Throwable throwable ) {
124
- if (!_confirmed ) {
125
- future .completeExceptionally (throwable );
126
- }
127
-
128
- Throwable error = throwable ;
129
- if (error instanceof StatusRuntimeException ) {
130
- StatusRuntimeException sre = (StatusRuntimeException ) error ;
131
- String desc = sre .getStatus ().getDescription ();
132
- if (sre .getStatus ().getCode () == Status .Code .CANCELLED && desc != null && desc .equals ("user-initiated" )) {
133
- listener .onCancelled (this ._subscription , null );
134
- return ;
135
- }
136
-
137
- String leaderHost = sre .getTrailers ().get (Metadata .Key .of ("leader-endpoint-host" , Metadata .ASCII_STRING_MARSHALLER ));
138
- String leaderPort = sre .getTrailers ().get (Metadata .Key .of ("leader-endpoint-port" , Metadata .ASCII_STRING_MARSHALLER ));
139
-
140
- if (leaderHost != null && leaderPort != null ) {
141
- error = new NotLeaderException (leaderHost , Integer .valueOf (leaderPort ));
142
- }
143
- }
144
-
145
- listener .onCancelled (this ._subscription , error );
146
- }
147
-
148
- @ Override
149
- public void onCompleted () {
150
- // Subscriptions should only complete on error.
151
- }
152
- };
46
+ StreamsOuterClass .ReadReq readReq = StreamsOuterClass .ReadReq .newBuilder ()
47
+ .setOptions (createOptions ())
48
+ .build ();
153
49
50
+ StreamsGrpc .StreamsStub streamsClient = GrpcUtils .configureStub (StreamsGrpc .newStub (args .getChannel ()), this .client .getSettings (), this .options );
154
51
streamsClient .read (readReq , observer );
52
+ });
155
53
156
- return future ;
54
+ return future ;
55
+ }
56
+
57
+ private ReadResponseObserver createObserver (WorkItemArgs args , CompletableFuture <Subscription > future ) {
58
+ StreamConsumer consumer = new SubscriptionStreamConsumer (this .listener , this .checkpointer , future , (subscriptionId , event , action ) -> {
59
+ ClientTelemetry .traceSubscribe (
60
+ action ,
61
+ subscriptionId ,
62
+ args .getChannel (),
63
+ client .getSettings (),
64
+ options .getCredentials (),
65
+ event );
157
66
});
67
+
68
+ return new ReadResponseObserver (this .options , consumer );
158
69
}
159
70
}
0 commit comments