15
15
*/
16
16
package com .vaadin .client .communication ;
17
17
18
+ import java .util .ArrayList ;
19
+ import java .util .List ;
20
+
18
21
import com .google .gwt .core .client .GWT ;
22
+ import com .google .gwt .user .client .Timer ;
19
23
20
24
import com .vaadin .client .ConnectionIndicator ;
21
25
import com .vaadin .client .Console ;
@@ -67,6 +71,10 @@ public enum ResynchronizationState {
67
71
68
72
private JsonObject pushPendingMessage ;
69
73
74
+ private List <JsonObject > messageQueue = new ArrayList <>();
75
+
76
+ private Timer resendMessageTimer ;
77
+
70
78
/**
71
79
* Creates a new instance connected to the given registry.
72
80
*
@@ -119,7 +127,10 @@ private void doSendInvocationsToServer() {
119
127
JsonObject payload = pushPendingMessage ;
120
128
pushPendingMessage = null ;
121
129
registry .getRequestResponseTracker ().startRequest ();
122
- send (payload );
130
+ sendPayload (payload );
131
+ return ;
132
+ } else if (hasQueuedMessages () && resendMessageTimer == null ) {
133
+ sendPayload (messageQueue .get (0 ));
123
134
return ;
124
135
}
125
136
@@ -146,6 +157,8 @@ private void doSendInvocationsToServer() {
146
157
if (resynchronizationState == ResynchronizationState .SEND_TO_SERVER ) {
147
158
resynchronizationState = ResynchronizationState .WAITING_FOR_RESPONSE ;
148
159
Console .warn ("Resynchronizing from server" );
160
+ messageQueue .clear ();
161
+ resetTimer ();
149
162
extraJson .put (ApplicationConstants .RESYNCHRONIZE_ID , true );
150
163
}
151
164
if (showLoadingIndicator ) {
@@ -166,7 +179,6 @@ protected void send(final JsonArray reqInvocations,
166
179
final JsonObject extraJson ) {
167
180
registry .getRequestResponseTracker ().startRequest ();
168
181
send (preparePayload (reqInvocations , extraJson ));
169
-
170
182
}
171
183
172
184
private JsonObject preparePayload (final JsonArray reqInvocations ,
@@ -177,10 +189,6 @@ private JsonObject preparePayload(final JsonArray reqInvocations,
177
189
payload .put (ApplicationConstants .CSRF_TOKEN , csrfToken );
178
190
}
179
191
payload .put (ApplicationConstants .RPC_INVOCATIONS , reqInvocations );
180
- payload .put (ApplicationConstants .SERVER_SYNC_ID ,
181
- registry .getMessageHandler ().getLastSeenServerSyncId ());
182
- payload .put (ApplicationConstants .CLIENT_TO_SERVER_ID ,
183
- clientToServerMessageId ++);
184
192
if (extraJson != null ) {
185
193
for (String key : extraJson .keys ()) {
186
194
JsonValue value = extraJson .get (key );
@@ -192,12 +200,44 @@ private JsonObject preparePayload(final JsonArray reqInvocations,
192
200
193
201
/**
194
202
* Sends an asynchronous or synchronous UIDL request to the server using the
195
- * given URI.
203
+ * given URI. Adds message to message queue and postpones sending if queue
204
+ * not empty.
196
205
*
197
206
* @param payload
198
207
* The contents of the request to send
199
208
*/
200
209
public void send (final JsonObject payload ) {
210
+ if (hasQueuedMessages ()) {
211
+ messageQueue .add (payload );
212
+ return ;
213
+ }
214
+ messageQueue .add (payload );
215
+ sendPayload (payload );
216
+ }
217
+
218
+ /**
219
+ * Sends an asynchronous or synchronous UIDL request to the server using the
220
+ * given URI.
221
+ *
222
+ * @param payload
223
+ * The contents of the request to send
224
+ */
225
+ private void sendPayload (final JsonObject payload ) {
226
+ payload .put (ApplicationConstants .SERVER_SYNC_ID ,
227
+ registry .getMessageHandler ().getLastSeenServerSyncId ());
228
+ // clientID should only be set and updated if payload doesn't contain
229
+ // clientID. If one exists we are probably trying to resend.
230
+ if (!payload .hasKey (ApplicationConstants .CLIENT_TO_SERVER_ID )) {
231
+ payload .put (ApplicationConstants .CLIENT_TO_SERVER_ID ,
232
+ clientToServerMessageId ++);
233
+ }
234
+
235
+ if (!registry .getRequestResponseTracker ().hasActiveRequest ()) {
236
+ // Direct calls to send from outside probably have not started
237
+ // request.
238
+ registry .getRequestResponseTracker ().startRequest ();
239
+ }
240
+
201
241
if (push != null && push .isBidirectional ()) {
202
242
// When using bidirectional transport, the payload is not resent
203
243
// to the server during reconnection attempts.
@@ -211,6 +251,31 @@ public void send(final JsonObject payload) {
211
251
} else {
212
252
Console .debug ("send XHR" );
213
253
registry .getXhrConnection ().send (payload );
254
+
255
+ resetTimer ();
256
+ // resend last payload if response hasn't come in.
257
+ resendMessageTimer = new Timer () {
258
+ @ Override
259
+ public void run () {
260
+ resendMessageTimer
261
+ .schedule (registry .getApplicationConfiguration ()
262
+ .getMaxMessageSuspendTimeout () + 500 );
263
+ if (!registry .getRequestResponseTracker ()
264
+ .hasActiveRequest ()) {
265
+ registry .getRequestResponseTracker ().startRequest ();
266
+ }
267
+ registry .getXhrConnection ().send (payload );
268
+ }
269
+ };
270
+ resendMessageTimer .schedule (registry .getApplicationConfiguration ()
271
+ .getMaxMessageSuspendTimeout () + 500 );
272
+ }
273
+ }
274
+
275
+ private void resetTimer () {
276
+ if (resendMessageTimer != null ) {
277
+ resendMessageTimer .cancel ();
278
+ resendMessageTimer = null ;
214
279
}
215
280
}
216
281
@@ -289,6 +354,8 @@ public String getCommunicationMethodName() {
289
354
*/
290
355
public void resynchronize () {
291
356
if (requestResynchronize ()) {
357
+ messageQueue .clear ();
358
+ resetTimer ();
292
359
sendInvocationsToServer ();
293
360
}
294
361
}
@@ -311,12 +378,24 @@ public void setClientToServerMessageId(int nextExpectedId, boolean force) {
311
378
ApplicationConstants .CLIENT_TO_SERVER_ID ) < nextExpectedId ) {
312
379
pushPendingMessage = null ;
313
380
}
381
+ if (hasQueuedMessages ()) {
382
+ // If queued message is the expected one. remove from queue
383
+ // and send next message if any.
384
+ if (messageQueue .get (0 )
385
+ .getNumber (ApplicationConstants .CLIENT_TO_SERVER_ID )
386
+ + 1 == nextExpectedId ) {
387
+ resetTimer ();
388
+ messageQueue .remove (0 );
389
+ }
390
+ }
314
391
return ;
315
392
}
316
393
if (force ) {
317
394
Console .debug (
318
395
"Forced update of clientId to " + clientToServerMessageId );
319
396
clientToServerMessageId = nextExpectedId ;
397
+ messageQueue .clear ();
398
+ resetTimer ();
320
399
return ;
321
400
}
322
401
@@ -372,4 +451,8 @@ void clearResynchronizationState() {
372
451
ResynchronizationState getResynchronizationState () {
373
452
return resynchronizationState ;
374
453
}
454
+
455
+ public boolean hasQueuedMessages () {
456
+ return !messageQueue .isEmpty ();
457
+ }
375
458
}
0 commit comments