github.com/go-kivik/kivik/v4@v4.3.2/couchdb/bulk.go (about) 1 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 2 // use this file except in compliance with the License. You may obtain a copy of 3 // the License at 4 // 5 // http://www.apache.org/licenses/LICENSE-2.0 6 // 7 // Unless required by applicable law or agreed to in writing, software 8 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 // License for the specific language governing permissions and limitations under 11 // the License. 12 13 package couchdb 14 15 import ( 16 "context" 17 "encoding/json" 18 "errors" 19 "net/http" 20 21 "github.com/go-kivik/kivik/v4/couchdb/chttp" 22 "github.com/go-kivik/kivik/v4/driver" 23 internal "github.com/go-kivik/kivik/v4/int/errors" 24 ) 25 26 func (d *db) BulkDocs(ctx context.Context, docs []interface{}, options driver.Options) ([]driver.BulkResult, error) { 27 chttpOpts := chttp.NewOptions(options) 28 opts := map[string]interface{}{} 29 options.Apply(opts) 30 opts["docs"] = docs 31 chttpOpts.GetBody = chttp.BodyEncoder(opts) 32 33 resp, err := d.Client.DoReq(ctx, http.MethodPost, d.path("/_bulk_docs"), chttpOpts) 34 if err != nil { 35 return nil, err 36 } 37 defer chttp.CloseBody(resp.Body) 38 39 switch resp.StatusCode { 40 case http.StatusCreated: 41 // Nothing to do 42 case http.StatusExpectationFailed: 43 err = &chttp.HTTPError{ 44 Response: resp, 45 Reason: "one or more document was rejected", 46 } 47 default: 48 // All other errors can consume the response body and return immediately 49 if e := chttp.ResponseError(resp); e != nil { 50 return nil, e 51 } 52 } 53 var temp []bulkDocResult 54 if err := chttp.DecodeJSON(resp, &temp); err != nil { 55 return nil, err 56 } 57 results := make([]driver.BulkResult, len(temp)) 58 for i, r := range temp { 59 results[i] = driver.BulkResult(r) 60 } 61 return results, err 62 } 63 64 type bulkDocResult struct { 65 ID string `json:"id"` 66 Rev string `json:"rev"` 67 Error error 68 } 69 70 func (r *bulkDocResult) UnmarshalJSON(p []byte) error { 71 target := struct { 72 *bulkDocResult 73 Error string `json:"error"` 74 Reason string `json:"reason"` 75 UnmarshalJSON struct{} 76 }{ 77 bulkDocResult: r, 78 } 79 if err := json.Unmarshal(p, &target); err != nil { 80 return err 81 } 82 switch target.Error { 83 case "": 84 // No error 85 case "conflict": 86 r.Error = &internal.Error{Status: http.StatusConflict, Err: errors.New(target.Reason)} 87 default: 88 r.Error = &internal.Error{Status: http.StatusInternalServerError, Err: errors.New(target.Reason)} 89 } 90 return nil 91 }