Handles a "proposeChanges" request, similar to "changes" but in no-conflicts mode
(rq *blip.Message)
| 815 | |
| 816 | // Handles a "proposeChanges" request, similar to "changes" but in no-conflicts mode |
| 817 | func (bh *blipHandler) handleProposeChanges(rq *blip.Message) error { |
| 818 | |
| 819 | // we don't know whether this batch of changes has completed because they look like unsolicited revs to us, |
| 820 | // but we can stop clients swarming us with these causing CheckProposedRev work |
| 821 | bh.inFlightChangesThrottle <- struct{}{} |
| 822 | defer func() { <-bh.inFlightChangesThrottle }() |
| 823 | |
| 824 | includeConflictRev := false |
| 825 | if val := rq.Properties[ProposeChangesConflictsIncludeRev]; val != "" { |
| 826 | includeConflictRev = val == trueProperty |
| 827 | } |
| 828 | |
| 829 | var changeList [][]interface{} |
| 830 | if err := rq.ReadJSONBody(&changeList); err != nil { |
| 831 | return err |
| 832 | } |
| 833 | bh.logEndpointEntry(rq.Profile(), fmt.Sprintf("#Changes: %d", len(changeList))) |
| 834 | if len(changeList) == 0 { |
| 835 | return nil |
| 836 | } |
| 837 | output := bytes.NewBuffer(make([]byte, 0, 5*len(changeList))) |
| 838 | output.Write([]byte("[")) |
| 839 | nWritten := 0 |
| 840 | |
| 841 | // proposeChanges stats |
| 842 | startTime := time.Now() |
| 843 | bh.replicationStats.HandleChangesCount.Add(int64(len(changeList))) |
| 844 | defer func() { |
| 845 | bh.replicationStats.HandleChangesTime.Add(time.Since(startTime).Nanoseconds()) |
| 846 | }() |
| 847 | versionVectorProtocol := bh.useHLV() |
| 848 | |
| 849 | for i, change := range changeList { |
| 850 | docID := change[0].(string) |
| 851 | rev := change[1].(string) // rev can represent a RevTree ID or HLV current version |
| 852 | parentRevID := "" |
| 853 | if len(change) > 2 { |
| 854 | parentRevID = change[2].(string) |
| 855 | } |
| 856 | var status ProposedRevStatus |
| 857 | var currentRev string |
| 858 | |
| 859 | changeIsVector := false |
| 860 | if versionVectorProtocol { |
| 861 | // TODO: CBG-4812 Use base.IsRevTreeID |
| 862 | changeIsVector = strings.Contains(rev, "@") |
| 863 | } |
| 864 | if versionVectorProtocol && changeIsVector { |
| 865 | proposedVersionStr := ExtractCVFromProposeChangesRev(rev) |
| 866 | status, currentRev = bh.collection.CheckProposedVersion(bh.loggingCtx, docID, proposedVersionStr, parentRevID, rev) |
| 867 | } else { |
| 868 | status, currentRev = bh.collection.CheckProposedRev(bh.loggingCtx, docID, rev, parentRevID) |
| 869 | } |
| 870 | if status == ProposedRev_OK_IsNew { |
| 871 | // Remember that the doc doesn't exist locally, in order to optimize the upcoming Put: |
| 872 | bh.collectionCtx.notePendingInsertion(docID) |
| 873 | } else if status != ProposedRev_OK { |
| 874 | // Reject the proposed change. |
nothing calls this directly
no test coverage detected