MCPcopy Create free account
hub / github.com/couchbase/sync_gateway / handleSubChanges

Method handleSubChanges

db/blip_handler.go:266–396  ·  view source on GitHub ↗

CHANGES Received a "subChanges" subscription request

(rq *blip.Message)

Source from the content-addressed store, hash-verified

264
265// Received a "subChanges" subscription request
266func (bh *blipHandler) handleSubChanges(rq *blip.Message) error {
267 latestSeq := func() (SequenceID, error) {
268 seq, err := bh.collection.LastSequence(bh.loggingCtx)
269 return SequenceID{Seq: seq}, err
270 }
271 subChangesParams, err := NewSubChangesParams(bh.loggingCtx, rq, latestSeq, bh.db.Options.ChangesRequestPlus)
272 if err != nil {
273 return base.HTTPErrorf(http.StatusBadRequest, "Invalid subChanges parameters")
274 }
275
276 // Ensure that only _one_ subChanges subscription can be open on this blip connection at any given time. SG #3222.
277 collectionCtx := bh.collectionCtx
278 collectionCtx.changesCtxLock.Lock()
279 defer collectionCtx.changesCtxLock.Unlock()
280 if !collectionCtx.activeSubChanges.CASRetry(false, true) {
281 collectionStr := "default collection"
282 if bh.collectionIdx != nil {
283 collectionStr = fmt.Sprintf("collection %d", *bh.collectionIdx)
284 }
285 return fmt.Errorf("blipHandler for %s already has an outstanding subChanges. Cannot open another one", collectionStr)
286 }
287
288 // Create ctx if it has been cancelled
289 if collectionCtx.changesCtx.Err() != nil {
290 collectionCtx.changesCtx, collectionCtx.changesCtxCancel = context.WithCancel(bh.loggingCtx)
291 }
292
293 if len(subChangesParams.docIDs()) > 0 && subChangesParams.continuous() {
294 return base.HTTPErrorf(http.StatusBadRequest, "DocIDs filter not supported for continuous subChanges")
295 }
296
297 bh.logEndpointEntry(rq.Profile(), subChangesParams.String())
298
299 var channels base.Set
300 if filter := subChangesParams.filter(); filter == base.ByChannelFilter {
301 var err error
302
303 channels, err = subChangesParams.channelsExpandedSet()
304 if err != nil {
305 return base.HTTPErrorf(http.StatusBadRequest, "%s", err)
306 } else if len(channels) == 0 {
307 return base.HTTPErrorf(http.StatusBadRequest, "Empty channel list")
308 }
309 } else if filter != "" {
310 return base.HTTPErrorf(http.StatusBadRequest, "Unknown filter; try sync_gateway/bychannel")
311 }
312
313 collectionCtx.channels = channels
314
315 clientType := clientTypeCBL2
316 if rq.Properties["client_sgr2"] == trueProperty {
317 clientType = clientTypeSGR2
318 }
319
320 continuous := subChangesParams.continuous()
321
322 requestPlusSeq := uint64(0)
323 // If non-continuous, check whether requestPlus handling is set for request or via database config

Callers

nothing calls this directly

Calls 15

docIDsMethod · 0.95
continuousMethod · 0.95
logEndpointEntryMethod · 0.95
StringMethod · 0.95
filterMethod · 0.95
channelsExpandedSetMethod · 0.95
requestPlusMethod · 0.95
sendReplacementRevsMethod · 0.95
sendChangesMethod · 0.95
SinceMethod · 0.95
activeOnlyMethod · 0.95
batchSizeMethod · 0.95

Tested by

no test coverage detected