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  }