github.com/ravendb/ravendb-go-client@v0.0.0-20240229102137-4474ee7aa0fa/batch_operation.go (about) 1 package ravendb 2 3 // BatchOperation represents a batch operation 4 type BatchOperation struct { 5 session *InMemoryDocumentSessionOperations 6 entities []interface{} 7 sessionCommandsCount int 8 } 9 10 func newBatchOperation(session *InMemoryDocumentSessionOperations) *BatchOperation { 11 return &BatchOperation{ 12 session: session, 13 } 14 } 15 16 func (b *BatchOperation) createRequest() (*BatchCommand, error) { 17 result, err := b.session.prepareForSaveChanges() 18 if err != nil { 19 return nil, err 20 } 21 22 b.sessionCommandsCount = len(result.sessionCommands) 23 result.sessionCommands = append(result.sessionCommands, result.deferredCommands...) 24 if len(result.sessionCommands) == 0 { 25 return nil, nil 26 } 27 28 if err = b.session.incrementRequestCount(); err != nil { 29 return nil, err 30 } 31 32 b.entities = result.entities 33 34 return newBatchCommand(b.session.GetConventions(), result.sessionCommands, result.options, b.session.transactionMode, b.session.disableAtomicDocumentWritesInClusterWideTransaction) 35 } 36 37 func (b *BatchOperation) setResult(serverResult *JSONArrayResult) error { 38 b.session.sessionInfo.lastClusterTransactionIndex = &serverResult.TransactionIndex 39 if b.session.transactionMode == TransactionMode_ClusterWide && serverResult.TransactionIndex <= 0 { 40 url, err := b.session.GetRequestExecutor().GetURL() 41 if err != nil { 42 url = "UNKOWN_URL" 43 } 44 return newIllegalStateError("Cluster transaction was send to a node that is not supporting it. So it was executed ONLY on the requested node on " + url) 45 } 46 47 result := serverResult.Results 48 if len(result) == 0 { 49 return throwOnNullResult() 50 } 51 52 for commandIndex := 0; commandIndex < b.sessionCommandsCount; commandIndex++ { 53 batchResult := result[commandIndex] 54 if batchResult == nil { 55 return newIllegalArgumentError("batchResult cannot be nil") 56 } 57 typ, _ := jsonGetAsText(batchResult, "Type") 58 59 switch typ { 60 case "PUT": 61 entity := b.entities[commandIndex] 62 documentInfo := getDocumentInfoByEntity(b.session.documentsByEntity, entity) 63 if documentInfo == nil { 64 continue 65 } 66 changeVector := jsonGetAsTextPointer(batchResult, MetadataChangeVector) 67 if changeVector == nil { 68 return newIllegalStateError("PUT response is invalid. @change-vector is missing on " + documentInfo.id) 69 } 70 id, _ := jsonGetAsText(batchResult, MetadataID) 71 if id == "" { 72 return newIllegalStateError("PUT response is invalid. @id is missing on " + documentInfo.id) 73 } 74 75 for propertyName, v := range batchResult { 76 if propertyName == "Type" { 77 continue 78 } 79 80 meta := documentInfo.metadata 81 meta[propertyName] = v 82 } 83 84 documentInfo.id = id 85 documentInfo.changeVector = changeVector 86 doc := documentInfo.document 87 doc[MetadataKey] = documentInfo.metadata 88 documentInfo.metadataInstance = nil 89 90 b.session.documentsByID.add(documentInfo) 91 b.session.generateEntityIDOnTheClient.trySetIdentity(entity, id) 92 93 afterSaveChangesEventArgs := newAfterSaveChangesEventArgs(b.session, documentInfo.id, documentInfo.entity) 94 b.session.onAfterSaveChangesInvoke(afterSaveChangesEventArgs) 95 break 96 case "CompareExchangePUT": 97 index, exist := batchResult["Index"].(float64) 98 if exist == false { 99 return newIllegalStateError("CompareExchangePUT is missing index property.") 100 } 101 key, exist := batchResult["Key"].(string) 102 if exist == false { 103 return newIllegalStateError("CompareExchangePUT is missing key property.") 104 } 105 clusterSession, err := b.session.GetClusterSession() 106 if err != nil { 107 return err 108 } 109 110 clusterSession.updateState(key, int64(index)) 111 break 112 default: 113 break 114 } 115 116 } 117 118 return nil 119 } 120 121 func (b *BatchOperation) setResultOld(result []map[string]interface{}) error { 122 if len(result) == 0 { 123 return throwOnNullResult() 124 } 125 for i := 0; i < b.sessionCommandsCount; i++ { 126 batchResult := result[i] 127 if batchResult == nil { 128 return newIllegalArgumentError("batchResult cannot be nil") 129 } 130 typ, _ := jsonGetAsText(batchResult, "Type") 131 if typ != "PUT" { 132 continue 133 } 134 entity := b.entities[i] 135 documentInfo := getDocumentInfoByEntity(b.session.documentsByEntity, entity) 136 if documentInfo == nil { 137 continue 138 } 139 changeVector := jsonGetAsTextPointer(batchResult, MetadataChangeVector) 140 if changeVector == nil { 141 return newIllegalStateError("PUT response is invalid. @change-vector is missing on " + documentInfo.id) 142 } 143 id, _ := jsonGetAsText(batchResult, MetadataID) 144 if id == "" { 145 return newIllegalStateError("PUT response is invalid. @id is missing on " + documentInfo.id) 146 } 147 148 for propertyName, v := range batchResult { 149 if propertyName == "Type" { 150 continue 151 } 152 153 meta := documentInfo.metadata 154 meta[propertyName] = v 155 } 156 157 documentInfo.id = id 158 documentInfo.changeVector = changeVector 159 doc := documentInfo.document 160 doc[MetadataKey] = documentInfo.metadata 161 documentInfo.metadataInstance = nil 162 163 b.session.documentsByID.add(documentInfo) 164 b.session.generateEntityIDOnTheClient.trySetIdentity(entity, id) 165 166 afterSaveChangesEventArgs := newAfterSaveChangesEventArgs(b.session, documentInfo.id, documentInfo.entity) 167 b.session.onAfterSaveChangesInvoke(afterSaveChangesEventArgs) 168 } 169 return nil 170 } 171 172 func throwOnNullResult() error { 173 return newIllegalStateError("Received empty response from the server. This is not supposed to happen and is likely a bug.") 174 }