-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Persistent Subscriptions
A PersistentSubscription is an Aeron Archive feature for replaying from a recording, then switching seamlessly to a
live stream; useful for late-joining applications. It also provides fallback support for slow consumers by always
returning to the replay if kicked off live.
It is an alternative to the existing ReplayMerge feature.
For intended usage, see the Persistent Subscription sample, as well as the system tests for Java, C and C++ Wrapper.
To configure a PersistentSubscription, pass a PersistentSubscription.Context to PersistentSubscription#create.
A sample with the required configuration options set is shown below.
final PersistentSubscription.Context context = new PersistentSubscription.Context()
.recordingId(12)
.startPosition(FROM_START)
.liveChannel("aeron:ipc")
.liveStreamId(1000)
.replayChannel("aeron:ipc")
.replayStreamId(1001)
.aeronArchiveContext(archiveContext);Note:
startPositiondefaults toPersistentSubscription#FROM_START(the beginning of the recording), but can be set to a specific position in the recording, orPersistentSubscription#FROM_LIVEto immediately join the live stream.
PersistentSubscription has both PersistentSubscription#poll and PersistentSubscription#controlledPoll for
consuming messages. These methods have the same signature as Subscription#poll and Subscription#controlledPoll
respectively.
int doWork()
{
return persistentSubscription.poll(fragmentHandler, fragmentLimit);
}Note: The
fragmentHandlerpassed to the subscription's polling methods should not be aFragmentAssembleras fragment assembly is handled within thePersistentSubscription.
Should an application need to know the current state of the subscription, the API has the following flags:
-
isLive- currently consuming from the live stream. -
isReplaying- currently replaying from a recording. -
hasFailed- the subscription has encountered a terminal error and has transitioned to aFAILEDstate. -
failureReason- the error that caused the subscription to get into aFAILEDstate.
There is also a PersistentSubscriptionListener that can be set on the context to receive callbacks on certain
state transitions:
-
onLiveJoined- called when the subscription starts consuming from live. -
onLiveLeft- called when the subscription falls off live. -
onError(Exception)- called when errors occur. These will not necessarily be terminal failures.
A PersistentSubscription is quite durable, typically attempting to re-connect to replay or live,
should any errors be encountered.
However, there are a few errors that are terminal, requiring the subscription to be re-initialized.
These can be detected via the aforementioned hasFailed and failureReason methods.
PersistentSubscription supports agent logging in Java and publishes four counters in all implementations.
The two agent logs for a PersistentSubscription are:
- State Change - logged on each state machine transition, includes old state, new state, recording ID, and channel/stream details.
- Joined Live - logged when the subscription switches to the live stream, includes recording ID, channel/stream details, live session ID, and join position.
- Left Live - logged when the subscription drops off the live stream, includes recording ID, channel/stream details, and the latest position on the live stream.
-
State - current state machine state. See the
Stateenum in io.aeron.archive.client.PersistentSubscription. -
Join difference - byte gap between replay position and live position when the live image is added.
Long.MIN_VALUEwhen not consuming from live. - Live joined count - number of times the subscription has switched to live.
- Live left count - number of times the subscription has dropped off the live stream.
As a general recommendation, if you aren't already using ReplayMerge, or you require IPC or Spies support, then use
PersistentSubscription. If you are using ReplayMerge and have no IPC or Spies support requirements, then there's
no need to switch since ReplayMerge is still actively supported and functional. A table of major differences can be
found below.
| PersistentSubscription | ReplayMerge | |
|---|---|---|
| IPC / Spy support | Yes | No |
| Falls back to replay | Yes | No |
| Memory overhead | Higher; Uses 2 .logbuffer
|
Lower; Uses 1 .logbuffer
|
| Does fragment assembly | Yes | No |