示例#1
0
func (es *fdbStore) Append(records []Envelope) (err error) {
	if es.reportMetrics {
		defer fsd.TimeSince("es.append", time.Now())
	}

	globalSpace := es.space.Sub(globalPrefix)

	_, err = es.db.Transact(func(tr fdb.Transaction) (interface{}, error) {

		for _, evt := range records {

			uuid := NewSequentialUUID()

			contract, data := evt.Payload()
			tr.Set(globalSpace.Sub(uuid, contract, "", 0), data)
		}

		return nil, nil
	})

	if es.reportMetrics {
		if nil == err {
			fsd.Count("es.append.ok", 1)
		} else {
			fsd.Count("es.append.fail", 1)
		}
	}

	return
}
示例#2
0
func (es *fdbStore) AppendToAggregate(aggregId string, expectedVersion int, records []Envelope) (err error) {

	if es.reportMetrics {
		defer fsd.TimeSince("es.append", time.Now())
	}

	globalSpace := es.space.Sub(globalPrefix)
	aggregSpace := es.space.Sub(aggregPrefix, aggregId)

	// TODO add random key to reduce contention

	_, err = es.db.Transact(func(tr fdb.Transaction) (interface{}, error) {
		// we are getting them in parallel
		aggregRecord := GetLastKeyFuture(tr, aggregSpace)

		//globalRecord := GetLastKeyFuture(tr.Snapshot(), globalSpace)

		nextAggregIndex := aggregRecord.MustGetNextIndex(0)

		switch expectedVersion {
		case ExpectedVersionAny:
			break
		case ExpectedVersionNone:
			if nextAggregIndex != 0 {
				return nil, &ErrConcurrencyViolation{
					aggregId,
					expectedVersion,
					nextAggregIndex - 1,
				}
			}
		default:
			if (nextAggregIndex - 1) != expectedVersion {
				return nil, &ErrConcurrencyViolation{
					aggregId,
					expectedVersion,
					nextAggregIndex - 1,
				}
			}
		}

		for i, evt := range records {
			aggregIndex := nextAggregIndex + i

			uuid := NewSequentialUUID()

			contract, data := evt.Payload()
			tr.Set(globalSpace.Sub(uuid, contract, aggregId, aggregIndex), data)
			tr.Set(aggregSpace.Sub(aggregIndex, contract), data)
		}

		return nil, nil
	})

	if es.reportMetrics {
		if nil == err {
			fsd.Count("es.append.ok", 1)
		} else {
			fsd.Count("es.append.fail", 1)
		}
	}

	return
}