Handles a "changes" request, i.e. a set of changes pushed by the client
(rq *blip.Message)
| 664 | |
| 665 | // Handles a "changes" request, i.e. a set of changes pushed by the client |
| 666 | func (bh *blipHandler) handleChanges(rq *blip.Message) error { |
| 667 | var ignoreNoConflicts bool |
| 668 | if val := rq.Properties[ChangesMessageIgnoreNoConflicts]; val != "" { |
| 669 | ignoreNoConflicts = val == trueProperty |
| 670 | } |
| 671 | |
| 672 | if !ignoreNoConflicts && !bh.collection.AllowConflicts() { |
| 673 | return ErrUseProposeChanges |
| 674 | } |
| 675 | |
| 676 | var changeList [][]interface{} |
| 677 | if err := rq.ReadJSONBody(&changeList); err != nil { |
| 678 | base.WarnfCtx(bh.loggingCtx, "Handle changes got error: %v", err) |
| 679 | return err |
| 680 | } |
| 681 | |
| 682 | collectionCtx := bh.collectionCtx |
| 683 | bh.logEndpointEntry(rq.Profile(), fmt.Sprintf("#Changes:%d", len(changeList))) |
| 684 | if len(changeList) == 0 { |
| 685 | // An empty changeList is sent when a one-shot replication sends its final changes |
| 686 | // message, or a continuous replication catches up *for the first time*. |
| 687 | // Note that this doesn't mean that rev messages associated with previous changes |
| 688 | // messages have been fully processed |
| 689 | if collectionCtx.emptyChangesMessageCallback != nil { |
| 690 | collectionCtx.emptyChangesMessageCallback() |
| 691 | } |
| 692 | return nil |
| 693 | } |
| 694 | output := bytes.NewBuffer(make([]byte, 0, 100*len(changeList))) |
| 695 | output.Write([]byte("[")) |
| 696 | jsonOutput := base.JSONEncoder(output) |
| 697 | nWritten := 0 |
| 698 | nRequested := 0 |
| 699 | |
| 700 | // Include changes messages w/ proposeChanges stats, although CBL should only be using proposeChanges |
| 701 | startTime := time.Now() |
| 702 | bh.replicationStats.HandleChangesCount.Add(int64(len(changeList))) |
| 703 | defer func() { |
| 704 | bh.replicationStats.HandleChangesTime.Add(time.Since(startTime).Nanoseconds()) |
| 705 | }() |
| 706 | |
| 707 | // DocID+RevID -> SeqNo |
| 708 | expectedSeqs := make(map[IDAndRev]SequenceID, 0) |
| 709 | alreadyKnownSeqs := make([]SequenceID, 0) |
| 710 | |
| 711 | versionVectorProtocol := bh.useHLV() |
| 712 | |
| 713 | for _, change := range changeList { |
| 714 | docID := change[1].(string) |
| 715 | rev := change[2].(string) |
| 716 | var missing, possible []string |
| 717 | |
| 718 | if !versionVectorProtocol { |
| 719 | missing, possible = bh.collection.RevDiff(bh.loggingCtx, docID, []string{rev}) |
| 720 | } else { |
| 721 | missing, possible = bh.collection.CheckChangeVersion(bh.loggingCtx, docID, rev) |
| 722 | } |
| 723 |
nothing calls this directly
no test coverage detected