github.com/altipla-consulting/ravendb-go-client@v0.1.3/subscription_batch.go (about)

     1  package ravendb
     2  
     3  import (
     4  	"log"
     5  	"reflect"
     6  )
     7  
     8  // SubscriptionBatchItem describes a single result from subscription
     9  type SubscriptionBatchItem struct {
    10  	Result       interface{}
    11  	ErrorMessage string
    12  	ID           string
    13  	ChangeVector string
    14  
    15  	RawResult   map[string]interface{}
    16  	RawMetadata map[string]interface{}
    17  	Metadata    *MetadataAsDictionary
    18  }
    19  
    20  func (i *SubscriptionBatchItem) throwItemProcessException() error {
    21  	return newIllegalStateError("Failed to process document " + i.ID + " with Change Vector " + i.ChangeVector + " because: \n" + i.ErrorMessage)
    22  }
    23  
    24  // GetResult sets result to to the value of that batch item
    25  func (i *SubscriptionBatchItem) GetResult(result interface{}) error {
    26  	if i.ErrorMessage != "" {
    27  		return i.throwItemProcessException()
    28  	}
    29  	if v, ok := result.(*map[string]interface{}); ok {
    30  		*v = i.RawResult
    31  		return nil
    32  	}
    33  	if err := checkValidLoadArg(result, "result"); err != nil {
    34  		return err
    35  	}
    36  	return setInterfaceToValue(result, i.Result)
    37  }
    38  
    39  func (i *SubscriptionBatchItem) GetMetadata() *MetadataAsDictionary {
    40  	if i.Metadata == nil {
    41  		i.Metadata = NewMetadataAsDictionary(i.RawMetadata, nil, "")
    42  	}
    43  
    44  	return i.Metadata
    45  }
    46  
    47  // SubscriptionBatch describes a bunch of results for subscription
    48  type SubscriptionBatch struct {
    49  	clazz           reflect.Type
    50  	revisions       bool
    51  	requestExecutor *RequestExecutor
    52  	store           *DocumentStore
    53  	dbName          string
    54  
    55  	logger                      *log.Logger
    56  	generateEntityIdOnTheClient *generateEntityIDOnTheClient
    57  
    58  	Items []*SubscriptionBatchItem
    59  }
    60  
    61  func (b *SubscriptionBatch) OpenSession() (*DocumentSession, error) {
    62  	sessionOptions := &SessionOptions{
    63  		Database:        b.dbName,
    64  		RequestExecutor: b.requestExecutor,
    65  	}
    66  	return b.store.OpenSessionWithOptions(sessionOptions)
    67  }
    68  
    69  func newSubscriptionBatch(clazz reflect.Type, revisions bool, requestExecutor *RequestExecutor, store *DocumentStore, dbName string, logger *log.Logger) *SubscriptionBatch {
    70  	res := &SubscriptionBatch{
    71  		clazz:           clazz,
    72  		revisions:       revisions,
    73  		requestExecutor: requestExecutor,
    74  		store:           store,
    75  		dbName:          dbName,
    76  		logger:          logger,
    77  	}
    78  
    79  	fn := func(entity interface{}) (string, error) {
    80  		panic("Shouldn't be generating new ids here")
    81  	}
    82  	c := res.requestExecutor.GetConventions()
    83  	res.generateEntityIdOnTheClient = newGenerateEntityIDOnTheClient(c, fn)
    84  	return res
    85  }
    86  
    87  func (b *SubscriptionBatch) initialize(batch []*subscriptionConnectionServerMessage) (string, error) {
    88  	b.Items = nil
    89  
    90  	lastReceivedChangeVector := ""
    91  
    92  	for _, item := range batch {
    93  		curDoc := item.Data
    94  		metadataI, ok := curDoc[MetadataKey]
    95  		if !ok {
    96  			return "", throwRequired("@metadata field")
    97  		}
    98  
    99  		metadata := metadataI.(map[string]interface{})
   100  		id, ok := jsonGetAsText(metadata, MetadataID)
   101  		if !ok {
   102  			return "", throwRequired("@id field")
   103  		}
   104  		changeVector, ok := jsonGetAsText(metadata, MetadataChangeVector)
   105  		if !ok {
   106  			return "", throwRequired("@change-vector field")
   107  		}
   108  		lastReceivedChangeVector = changeVector
   109  		if b.logger != nil {
   110  			b.logger.Printf("Got %s (change vector: [%s], size: %d)", id, lastReceivedChangeVector, len(curDoc))
   111  		}
   112  		var instance interface{}
   113  
   114  		if item.Exception == "" {
   115  			if b.clazz == reflect.TypeOf(map[string]interface{}{}) {
   116  				instance = curDoc
   117  			} else {
   118  				if b.revisions {
   119  					// parse outer object manually as Previous/Current has PascalCase
   120  					previous := curDoc["Previous"]
   121  					current := curDoc["Current"]
   122  					revision := &Revision{}
   123  					//c := b._requestExecutor.GetConventions()
   124  					if current != nil {
   125  						doc := current.(map[string]interface{})
   126  						v, err := entityToJSONConvertToEntity(b.clazz, id, doc)
   127  						if err != nil {
   128  							return "", err
   129  						}
   130  						revision.Current = v
   131  					}
   132  					if previous != nil {
   133  						doc := previous.(map[string]interface{})
   134  						v, err := entityToJSONConvertToEntity(b.clazz, id, doc)
   135  						if err != nil {
   136  							return "", err
   137  						}
   138  						revision.Previous = v
   139  					}
   140  					instance = revision
   141  				} else {
   142  					var err error
   143  					instance, err = entityToJSONConvertToEntity(b.clazz, id, curDoc)
   144  					if err != nil {
   145  						return "", err
   146  					}
   147  				}
   148  			}
   149  
   150  			if stringIsNotEmpty(id) {
   151  				b.generateEntityIdOnTheClient.trySetIdentity(instance, id)
   152  			}
   153  		}
   154  		itemToAdd := &SubscriptionBatchItem{
   155  			ChangeVector: changeVector,
   156  			ID:           id,
   157  			RawResult:    curDoc,
   158  			RawMetadata:  metadata,
   159  			Result:       instance,
   160  			ErrorMessage: item.Exception,
   161  		}
   162  		b.Items = append(b.Items, itemToAdd)
   163  	}
   164  	return lastReceivedChangeVector, nil
   165  }
   166  
   167  func throwRequired(name string) error {
   168  	return newIllegalStateError("Document must have a " + name)
   169  }