Skip to content

Commit 72e9101

Browse files
bczomamdspielman
authored andcommitted
New feature tutorial and sample for Message Replay (#45)
* Added new sample code for message replay and initial document Also updated Solace logo
1 parent 7d074b2 commit 72e9101

12 files changed

+613
-6
lines changed

NOTICE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
This product includes software originally developed by Solace Corporation
2-
Copyright 2016-2017 Solace Corporation
2+
Copyright 2016-2019 Solace Corporation

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ This repository contains:
3030
- [Event Monitor](https://github.com/SolaceSamples/solace-samples-javascript/tree/master/src/features/EventMonitor): Learn how to monitor message router generated events.
3131
- [GuaranteedRequestor/Replier](https://github.com/SolaceSamples/solace-samples-javascript/tree/master/src/features): Learn how to set up guaranteed request/reply messaging.
3232
- [NoLocal Pub-Sub](https://github.com/SolaceSamples/solace-samples-javascript/tree/master/src/features/NoLocalPubSub): Learn how to prevent messages published on a session or consumer received on that same session or consumer.
33+
- [Message Replay](https://github.com/SolaceSamples/solace-samples-javascript/tree/master/src/features/MessageReplay): Learn how to initiate and process the replay of previously published messages, as well as deal with an externally initiated replay.
3334

3435
## Checking out
3536

_config.yml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Site settings
2-
title: Solace Samples Javascript
2+
title: Solace Samples JavaScript
33
summary: These tutorials get you up to speed sending and receiving messages with Solace technology.
44
baseurl: "/solace-samples-javascript"
55
repository: https://github.com/SolaceSamples/solace-samples-javascript
@@ -8,15 +8,21 @@ repository: https://github.com/SolaceSamples/solace-samples-javascript
88

99
# Links
1010
advanced-samples: //github.com/SolaceSamples/solace-samples-javascript/tree/master/src/advanced-samples
11-
links-community: //dev.solace.com/community/
1211
links-downloads: //dev.solace.com/downloads/
12+
links-community: //dev.solace.com/community/
1313
links-get-started-javascript: //dev.solace.com/get-started/javascript-tutorials/
14-
links-solaceCloud-setup: //cloud.solace.com/create-messaging-service/
1514
links-tech-other: //dev.solace.com/tech/#other
15+
links-solaceCloud-setup: //cloud.solace.com/create-messaging-service/
1616
docs-core-concepts: //docs.solace.com/Features/Core-Concepts.htm
1717
docs-session-events: //docs.solace.com/Solace-Messaging-APIs/Creating-Client-Sessions-1.htm#Handle-Sess-Events
1818
docs-api-reference: //docs.solace.com/API-Developer-Online-Ref-Documentation/js/index.html
1919
docs-semp: //docs.solace.com/SEMP/Using-SEMP-to-Manage-and-Monitor-Routers.htm
2020
docs-topic-mapping: //docs.solace.com/Features/Core-Concepts.htm#topic-queue-mapping
2121
docs-dte: //docs.solace.com/Features/Endpoints.htm
2222
docs-active-flow-indication: //docs.solace.com/Solace-PubSub-Messaging-APIs/Developer-Guide/Creating-Flows.htm#Active-Flow-Indication
23+
docs-psplus-manager: //docs.solace.com/Solace-PubSub-Manager/PubSub-Manager-Overview.htm
24+
docs-semp-api: //docs.solace.com/SEMP/Using-SEMP.htm
25+
docs-endpoints: //docs.solace.com/Messaging-Basics/Endpoints.htm#Endpoints
26+
docs-api-errorresponse-subcode-ex: //docs.solace.com/API-Developer-Online-Ref-Documentation/js/solace.ErrorSubcode.html
27+
docs-replay-use-cases: //docs.solace.com/Features/Message-Replay.htm#Applicat
28+
docs-replay-cli-config: //docs.solace.com/Configuring-and-Managing/Msg-Replay-Config.htm
35 KB
Loading
79.4 KB
Loading

_docs/feature_MessageReplay.md

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
---
2+
layout: features
3+
title: Message Replay
4+
summary: Learn how to make use of Message Replay via the Solace JavaScript client library
5+
links:
6+
- label: MessageReplay.html
7+
link: /blob/master/src/features/MessageReplay/MessageReplay.html
8+
- label: MessageReplay.js
9+
link: /blob/master/src/features/MessageReplay/MessageReplay.js
10+
---
11+
12+
In this introduction we show you how a client can initiate and process the replay of previously published messages, as well as deal with an externally initiated replay.
13+
14+
## Feature Overview
15+
16+
During normal publishing, guaranteed messages will be removed from the message broker's [queue or topic endpoint]({{ site.docs-endpoints }}) once the consumer acknowledges their receipt or successful processing. When Message Replay is initiated for an endpoint, the message broker will re-publish a requested subset of previously published and logged messages, which enables the client to process these messages again.
17+
18+
Message Replay can be used if a client needs to catch up with missed messages as well as for several other [use cases]({{ site.docs-replay-use-cases }}).
19+
20+
Message Replay for an endpoint can be initiated programmatically from an API client connected to an exclusive endpoint, or administratively from the message broker. After the replay is done, the connected client will keep getting live messages delivered.
21+
22+
It's important to note that when initiating replay, the message broker will disconnect all connected client flows, active or not. A new flow needs to be started for a client wishing to receive replayed and subsequent messages. The only exception is that in the client initiated case the flow initiating the replay will not be disconnected.
23+
24+
## Prerequisite
25+
26+
A replay log must be created on the message broker for the Message VPN using [Message Replay CLI configuration]({{ site.docs-replay-cli-config }}) or using [Solace PubSub+ Manager]({{ site.docs-psplus-manager }}) administration console. Another option for configuration is to use the [SEMP API]({{ site.docs-semp-api }}).
27+
28+
NOTE: Message Replay is supported on Solace PubSub+ 3530 and 3560 appliances running release 9.1 and greater, and on the Solace PubSub+ software message broker running release 9.1 and greater. Solace JavaScript API version 10.2.1 or later is required.
29+
30+
![alt text]({{ site.baseurl }}/assets/images/config-replay-log.png "Configuring Replay Log using Solace PubSub+ Manager")
31+
<br>
32+
33+
## Code
34+
35+
### Checking for Message Replay capability
36+
37+
Message Replay must be supported on the message broker, so this should be the first thing the code checks:
38+
39+
```javascript
40+
if (!consumer.session.isCapable(solace.CapabilityType.MESSAGE_REPLAY)) {
41+
consumer.log('Message Replay is not supported on this message broker, disconnecting...');
42+
try {
43+
consumer.session.disconnect();
44+
} catch (error) {
45+
consumer.log(error.toString());
46+
}
47+
}
48+
```
49+
50+
### Initiating replay
51+
52+
First, a `replayStartLocation` object needs to be created to specify the desired subset of messages in the replay log.
53+
54+
There are two options:
55+
* use `createReplayStartLocationBeginning()` to replay all logged messages
56+
* use `createReplayStartLocationDate(Date date)` to replay all logged messages received starting from a specified `date`. Note the different possible formats in the example including how to specify the time zone.
57+
58+
Note: The `date` can’t be earlier than the date the replay log was created, otherwise replay will fail.
59+
60+
```javascript
61+
consumer.replayStartLocation = solace.SolclientFactory.createReplayStartLocationBeginning();
62+
/***************************************************************
63+
* Alternative replay start specifications to try instead of
64+
* createReplayStartLocationBeginning().
65+
*/
66+
/* Milliseconds after the Jan 1st of 1970 UTC+0: */
67+
// consumer.replayStartLocation = solace.SolclientFactory.createReplayStartLocationDate(
68+
// new Date(1554331492));
69+
70+
/* RFC3339 UTC date with timezone offset 0: */
71+
// consumer.replayStartLocation = solace.SolclientFactory.createReplayStartLocationDate(
72+
// new Date(Date.parse('2019-04-03T18:48:00Z')));
73+
74+
/* RFC3339 date with timezone: */
75+
// consumer.replayStartLocation = solace.SolclientFactory.createReplayStartLocationDate(
76+
// new Date(Date.parse('2019-04-03T18:48:00-05:00')));
77+
```
78+
79+
Indicate that replay is requested by setting a non-null `replayStartLocation` in `solace.MessageConsumerProperties`, which is then passed to `createMessageConsumer()` as a parameter.
80+
81+
The target endpoint (`queueDescriptor`) for replay is also set in `ConsumerFlowProperties` below, which is the normal way of setting an endpoint for a consumer flow.
82+
83+
```javascript
84+
consumer.replayStartLocation = solace.SolclientFactory.createReplayStartLocationBeginning();
85+
:
86+
// Create a message consumer
87+
consumer.messageConsumer = consumer.session.createMessageConsumer({
88+
// solace.MessageConsumerProperties
89+
queueDescriptor: { name: consumer.queueName, type: solace.QueueType.QUEUE },
90+
acknowledgeMode: solace.MessageConsumerAcknowledgeMode.CLIENT, // Enabling Client ack
91+
replayStartLocation: consumer.replayStartLocation,
92+
});
93+
:
94+
consumer.messageConsumer.connect();
95+
```
96+
97+
### Replay-related events
98+
99+
If a replay-related event occurs, the consumer flow is disconnected and a `solace.MessageConsumerEventName.DOWN_ERROR` event is generated with a specific Subcode, which can be processed in an event handler.
100+
101+
Some of the important Subcodes:
102+
* REPLAY_STARTED - a replay has been administratively started from the message broker; the consumer flow is being disconnected.
103+
* REPLAY_START_TIME_NOT_AVAILABLE - the requested replay start date is before when the replay log was created or in the future, which is not allowed
104+
* REPLAY_FAILED - indicates that an unexpected error has happened during replay
105+
106+
For the definition of additional replay-related Subcodes refer to `solace.ErrorSubcode` in the [JavaScript API Reference]({{ site.docs-api-errorresponse-subcode-ex }}) (search for REPLAY).
107+
108+
Here we will define the event handler to process events with some more example Subcodes.
109+
110+
```javascript
111+
consumer.messageConsumer.on(solace.MessageConsumerEventName.DOWN_ERROR, function (details) {
112+
consumer.consuming = false;
113+
consumer.log('Received "DOWN_ERROR" event - details: ' + details);
114+
switch(details.subcode) {
115+
case solace.ErrorSubcode.REPLAY_STARTED:
116+
:
117+
break;
118+
case solace.ErrorSubcode.REPLAY_START_TIME_NOT_AVAILABLE:
119+
:
120+
break;
121+
// Additional events example, may add specific handler code under each:
122+
case solace.ErrorSubcode.REPLAY_FAILED:
123+
case solace.ErrorSubcode.REPLAY_CANCELLED:
124+
case solace.ErrorSubcode.REPLAY_LOG_MODIFIED:
125+
case solace.ErrorSubcode.REPLAY_MESSAGE_UNAVAILABLE:
126+
case solace.ErrorSubcode.REPLAY_MESSAGE_REJECTED:
127+
break;
128+
default:
129+
consumer.log('=== An error happened, the message consumer is down ===');
130+
}
131+
```
132+
133+
In this example two specific Subcodes are handled:
134+
135+
* REPLAY_STARTED is handled by creating a new flow with no client-initiated message replay.
136+
* REPLAY_START_TIME_NOT_AVAILABLE is handled by adjusting `replayStartLocation` to replay all logged messages.
137+
138+
```
139+
case solace.ErrorSubcode.REPLAY_STARTED:
140+
consumer.log('Router initiating replay, reconnecting flow to receive messages.');
141+
consumer.replayStartLocation = null; // Client-initiated replay is not neeeded here
142+
consumer.createFlow();
143+
break;
144+
case solace.ErrorSubcode.REPLAY_START_TIME_NOT_AVAILABLE:
145+
consumer.log('Replay log does not cover requested time period, reconnecting flow for full log instead.');
146+
consumer.replayStartLocation = solace.SolclientFactory.createReplayStartLocationBeginning();
147+
consumer.createFlow();
148+
break;
149+
```
150+
151+
## Running the Sample
152+
153+
Follow the instructions to [check out and run the samples]({{ site.repository }}/blob/master/README.md#checking-out ).
154+
155+
Before running this sample, be sure that Message Replay is enabled in the Message VPN. Also, create an exclusive queue with the name "tutorial/queue" and messages must have been published to the replay log for this queue:
156+
157+
* Use the "QueueProducer" sample from `src/basic-samples/QueueProducer` in your cloned repo to create and publish one message to the queue. To start, simply load `QueueConsumer.html` into you browser.
158+
* Use the "QueueConsumer" sample from `src/basic-samples/QueueConsumer` to drain the queue so that replay is performed on an empty queue and observed by this sample. Both samples are from the [Persistence with Queues]({{ site.baseurl }}/persistence-with-queues) tutorial and they are using "tutorial/queue" by default. Note: after draining, disconnect the "QueueConsumer" from the queue because there can be only one consumer flow active on an exclusive queue at any time and the replay sample will need to connect a new one.
159+
160+
At this point the replay log has one message.
161+
162+
You can now run this sample and observe the following, particularly the "messageId"s listed.
163+
164+
1. First, use "MessageReplay" from `src/features/MessageReplay` for a client initiated replay. All messages are requested and replayed from the replay log.
165+
2. After replay the application is able to receive live messages. Try it by publishing a new message using the "QueueProducer" sample. Note that this message will also be added to the replay log.
166+
3. Now start a replay from the message broker. The "MessageReplay" flow event handler monitors for a replay start event. When the message broker initiates a replay, the flow will see a DOWN_ERROR event with cause REPLAY_STARTED. This means an administrator has initiated a replay, and the application must destroy and re-create the flow to receive the replayed messages.
167+
This will replay all logged messages including the live one published in step 2.
168+
169+
![alt text]({{ site.baseurl }}/assets/images/initiate-replay.png "Initiating Replay using Solace PubSub+ Manager")
170+
<br>
171+
172+
## Learn More
173+
174+
<ul>
175+
{% for item in page.links %}
176+
<li>Related Source Code: <a href="{{ site.repository }}{{ item.link }}" target="_blank">{{ item.label }}</a></li>
177+
{% endfor %}
178+
<li><a href="https://docs.solace.com/Features/Message-Replay.htm" target="_blank">Solace Feature Documentation</a></li>
179+
</ul>
180+

_docs/tutorials.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99
features:
1010
- feature_ActiveConsumerIndication
1111
- feature_DTEConsumer
12+
- feature_MessageReplay
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
<!DOCTYPE html>
2+
<!--
3+
Licensed to the Apache Software Foundation (ASF) under one
4+
or more contributor license agreements. See the NOTICE file
5+
distributed with this work for additional information
6+
regarding copyright ownership. The ASF licenses this file
7+
to you under the Apache License, Version 2.0 (the
8+
"License"); you may not use this file except in compliance
9+
with the License. You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing,
14+
software distributed under the License is distributed on an
15+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
KIND, either express or implied. See the License for the
17+
specific language governing permissions and limitations
18+
under the License.
19+
-->
20+
21+
<!--
22+
Solace Web Messaging API for JavaScript
23+
Message Replay tutorial - Queue Consumer
24+
Demonstrates the use of Message Replay from the API client
25+
-->
26+
27+
<html lang="en">
28+
29+
<head>
30+
<title>Solace Web Messaging API for JavaScript, Message Replay tutorial</title>
31+
<meta http-equiv="X-UA-Compatible" content="IE=edge;" />
32+
<meta charset="utf-8"/>
33+
34+
<link rel="stylesheet" type="text/css" href="../../resources/css/pure.css"></link>
35+
<link rel="stylesheet" type="text/css" href="../../resources/css/samples.css"></link>
36+
37+
<!-- Load Solace Web Messaging API for JavaScript -->
38+
<script src="../../../lib/solclient-debug.js"></script>
39+
40+
<!-- Load the Message Replay -->
41+
<script src="MessageReplay.js"></script>
42+
43+
<!-- Execute the Message Replay tutorial -->
44+
<script>
45+
var subscriberWithReplay = null;
46+
window.onload = function () {
47+
// Initialize factory with the most recent API defaults
48+
var factoryProps = new solace.SolclientFactoryProperties();
49+
factoryProps.profile = solace.SolclientFactoryProfiles.version10;
50+
solace.SolclientFactory.init(factoryProps);
51+
52+
// enable logging to JavaScript console at WARN level
53+
// NOTICE: works only with "solclientjs-debug.js"
54+
solace.SolclientFactory.setLogLevel(solace.LogLevel.WARN);
55+
56+
// create the consumer, specifying name of the queue
57+
subscriberWithReplay = new QueueConsumer('tutorial/queue');
58+
// assign buttons to the subscriber functions
59+
document.getElementById("connect").addEventListener("click", subscriberWithReplay.connect);
60+
document.getElementById("disconnect").addEventListener("click", subscriberWithReplay.disconnect);
61+
document.getElementById("startreplay").addEventListener("click", subscriberWithReplay.startReplay);
62+
document.getElementById("stopconsume").addEventListener("click", subscriberWithReplay.stopConsume);
63+
};
64+
function iframeloaded(){
65+
if (subscriberWithReplay) {
66+
subscriberWithReplay.connectToSolace();
67+
}
68+
};
69+
</script>
70+
<style>
71+
.warning {
72+
padding: 5px;
73+
border: 1px solid black;
74+
background-color: #ff8;
75+
}
76+
.ie11 {
77+
/* Hide instructions that only apply to IE11/Edge */
78+
display: none;
79+
}
80+
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
81+
.ie11 {
82+
/* Show instructions in IE11. If you're trying this sample from the local filesystem,
83+
it's easy to miss the prompt at the bottom of the window. */
84+
display: block !important;
85+
}
86+
}
87+
</style>
88+
</head>
89+
90+
<body>
91+
<!-- used to prompt selection of client certificate -->
92+
<iframe id="iframe" src="" onload="iframeloaded()" hidden></iframe>
93+
94+
<div class="banner">
95+
<div class="banner-interior">
96+
<span class="logo">
97+
<a href="http://dev.solace.com/">
98+
<img src="../../resources/images/solace-logo-white.png"/>
99+
</a>
100+
</span>
101+
<div class="banner-heading">
102+
Solace Web Messaging API for JavaScript
103+
</div>
104+
</div>
105+
</div>
106+
107+
<div class="doc-body">
108+
<h2>Message Replay tutorial</h2>
109+
<!--[if IE]>
110+
<div class="ie9 warning" style="padding: 5px; border: 1px solid black; background-color: #ff8;">
111+
IE9 only: If you are running this sample from the local filesystem, click the "Allow blocked content" button
112+
in the popup below to enable JavaScript.
113+
</div>
114+
<![endif]-->
115+
<div class="ie11 warning">
116+
IE 11 only: If you are running this sample from the local filesystem, click the "Allow blocked content" button
117+
in the popup below to enable JavaScript.
118+
</div>
119+
120+
<form class="pure-form pure-form-aligned">
121+
<fieldset>
122+
123+
<div class="pure-control-group">
124+
<label for="hosturl">Solace router host url</label>
125+
<input id="hosturl" type="text" placeholder="<protocol://host[:port]>">
126+
</div>
127+
128+
<div class="pure-control-group">
129+
<label for="message-vpn">Message-vpn</label>
130+
<input id="message-vpn" type="text" placeholder="Message VPN" value="default">
131+
</div>
132+
133+
<div class="pure-control-group">
134+
<label for="username">Username</label>
135+
<input id="username" type="text" placeholder="Username">
136+
</div>
137+
138+
<div class="pure-control-group">
139+
<label for="password">Password</label>
140+
<input id="password" type="password" placeholder="Password">
141+
</div>
142+
143+
</fieldset>
144+
<p>
145+
<button type="button" class="pure-button pure-button-primary" id="connect">Connect</button>
146+
<button type="button" class="pure-button button-error" id="disconnect">Disconnect</button>
147+
</p>
148+
<p>
149+
<button type="button" class="pure-button pure-button-primary" id="startreplay">Initiate message replay</button>
150+
<button type="button" class="pure-button button-error" id="stopconsume">Stop consuming</button>
151+
</p>
152+
153+
<textarea id="log" rows="20" cols="90" autofocus></textarea>
154+
155+
</form>
156+
157+
</div>
158+
159+
</body>
160+
161+
</html>
162+

0 commit comments

Comments
 (0)