Bug 10 - Create a CANCEL SUBSCRIPTION command
Summary: Create a CANCEL SUBSCRIPTION command
Status: RESOLVED WONTFIX
Alias: None
Product: Slony-I
Classification: Unclassified
Component: slon (show other bugs)
Version: devel
Hardware: All All
: medium enhancement
Assignee: Slony Bugs List
URL: http://lists.slony.info/pipermail/slo...
: 20 (view as bug list)
Depends on: 111
Blocks:
  Show dependency tree
 
Reported: 2007-11-13 13:07 UTC by Christopher Browne
Modified: 2010-08-16 07:51 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Christopher Browne 2007-11-13 13:07:02 UTC
This command will inject a CANCEL_SUBSCRIPTION event at event node #3
which will cancel any SUBSCRIBE SET events for set #2 on node #4.

1.  SUBSCRIBE SET event "hook"

We would then add a "hook" at the beginning of the code that detects
SUBSCRIBE SET events; this hook would search the provider node to see
if it has any CANCEL_SUBSCRIPTION events for the set in question that
are newer than the present SUBSCRIBE_SET event.  If that be the case,
it would not bother performing anything further of the subscription.[1]

There wind up being two possibilities:

- Supposing the SUBSCRIBE SET wasn't yet in progress when the CANCEL
  SUBSCRIPTION request came in, no (further) attempt would be made to
  set up the subscription.  Perfect!  That's exactly what we asked for.

- Alternatively, it is possible that the SUBSCRIBE SET request may
  have already completed.  If the subscription was in progress at the
  time that the CANCEL request came in, there isn't much of a way (short
  of polling periodically inside the code that processes this) to force
  cancellation.  One might force this by signalling the slon with
  SIGTERM/SIGKILL; when it restarts, the re-attempt to process the event
  would take us back to the first case...

  ... But absent of that, the subscription may indeed complete.
  We nonetheless need to eliminate the subscription as other nodes will
  likely by this time have been informed of the elimination of this
  subscription.  [2]

  Thus, we need to perform the equivalent to "UNSUBSCRIBE SET" at that
  point.

2.  SYNC event "hook"

We'll wind up needing a similar hook in SYNC to what's in SUBSCRIBE
SET, I think, so that if there is an outstanding CANCEL_SUBSCRIPTION
for the local node's subscription, we arrange to do the equivalent to
"UNSUBSCRIBE SET".

3.  CANCEL SUBSCRIPTION event

On the node where the set is, this will either be a NO-OP, if the
subscription is already cancelled, or this will do "UNSUBSCRIBE SET,"
as with the earlier hooks on SUBSCRIBE SET and SYNC, if it is still
active.

On nodes other than the receiver node for the subscription, the CANCEL
SUBSCRIPTION event would perform the equivalent to "UNSUBSCRIBE SET"
to indicate the cancellation of the subscription.[3]

Footnotes: 

[1] Note that if someone accidentally submitted a whole series of
SUBSCRIBE SET requests, it only takes ONE request to CANCEL
SUBSCRIPTION to turn them all into NOOPs.

[2] Note that we can't simply say "Oh, the subscription *DID* work,
we'll keep that!" as the effect of CANCEL SUBSCRIPTION will have been
to drop info about the subscription from other nodes.  We *must* kill
off the subscription even though it might have worked.

[3] Open question: Should the CANCEL SUBSCRIPTION event wait until its
location in sequence to be processed on the other nodes (e.g.  - nodes
other than the specified receiver), or should we have it invoked via
the hook in SYNC?  I'm not certain...
Comment 1 Christopher Browne 2008-02-27 09:25:24 UTC
Describing this in greater detail...  Please ignore the earlier discussion...

Consider the slonik statement:
cancel subscription (id=1, origin=1, receiver=3);

Where the subscription arrangement is to be...

  1 --> 2 --> 3 --> 4

Firstly, there are failure cases where this SHOULD fail:
- If node #3 is subscribed, according to node 3, and is feeding #4, according to node #3, then the request should FAIL!  Nothing's broken!  Moreover, we can't drop the subscription without causing other breakage (e.g. - leaving a downstream node, that also appears to be working, orphaned).
- If node #3 subscription is complete, according to node #3, then FAIL!  Again, nothing's broken with node #3.

Some Impossibilities

- Requests to subscribe to #3 will fail until node #2 has been subscribed.
- Therefore, we don't need to worry about cases where upstream subscriptions aren't ready.  We can focus on node #3 alone.
- There is never a reason to need to look at node #2; only #1 and #3 need to be considered.

There are now really only the following cases:

1.  Subscribe set hasn't been processed against node #3. 

We inject code into SUBSCRIBE SET that looks for a CANCEL SUBSCRIPTION later in the event stream, and if it is found, it replaces SUBSCRIBE_SET with CANCEL_SUBSCRIPTION, in sl_event, does a COMMIT on that, and then "fails."  The slon will reattempt the event, find a CANCEL_SUBSCRIPTION.

2.  Subscribe set has been processed, but not the "enable subscription" event.

We inject code as above into ENABLE SUBSCRIPTION.

3.  Enable subscription is in progress.

There may be a race condition here, where the subscription may complete before we get done; if that is the case, then the subscription will have succeeded, and we're too late to cancel it.

Absent of that, the slonik request should follow CANCEL SUBSCRIPTION (id, origin, receiver) with RESTART NODE (id=receiver).  That will cause the slon for the subscriber node to shutdown and restart itself, and, assuming the subscription was not complete, this will lead to the slon retrying the ENABLE_SUBSCRIPTION event,which will cause it to perform the logic of #2, above
Comment 2 Christopher Browne 2008-03-03 08:57:12 UTC
*** Bug 20 has been marked as a duplicate of this bug. ***
Comment 3 Jan Wieck 2010-08-13 14:04:45 UTC
This should be obsolete if we get bug 111 right. UNSUBSCRIBE SET would have the functionality of CANCEL SUBSCRIPTION.