Example #1
0
// Save appends all events in the event stream to the database.
func (s *EventStore) Save(events []eh.Event, originalVersion int) error {
	if len(events) == 0 {
		return eh.ErrNoEventsToAppend
	}

	// Build all event records, with incrementing versions starting from the
	// original aggregate version.
	eventRecords := make([]*eventRecord, len(events))
	aggregateID := events[0].AggregateID()
	for i, event := range events {
		// Only accept events belonging to the same aggregate.
		if event.AggregateID() != aggregateID {
			return ErrInvalidEvent
		}

		// Marshal event payload.
		payload, err := dynamodbattribute.MarshalMap(event)
		if err != nil {
			// return ErrCouldNotMarshalEvent
			return err
		}

		// Create the event record with current version and timestamp.
		eventRecords[i] = &eventRecord{
			AggregateID: event.AggregateID().String(),
			Version:     1 + originalVersion + i,
			Timestamp:   time.Now(),
			EventType:   event.EventType(),
			Payload:     payload,
		}
	}

	// TODO: Implement atomic version counter for the aggregate.
	// TODO: Batch write all events.
	for _, record := range eventRecords {
		// Marshal and store the event record.
		item, err := dynamodbattribute.MarshalMap(record)
		if err != nil {
			return err
		}
		putParams := &dynamodb.PutItemInput{
			TableName:           aws.String(s.config.Table),
			ConditionExpression: aws.String("attribute_not_exists(AggregateID) AND attribute_not_exists(Version)"),
			Item:                item,
		}
		if _, err = s.service.PutItem(putParams); err != nil {
			if err, ok := err.(awserr.RequestFailure); ok && err.Code() == "ConditionalCheckFailedException" {
				return ErrCouldNotSaveAggregate
			}
			return err
		}
	}

	return nil
}
Example #2
0
// SaveUser creates or updates a user. Upon creation, users are assigned a unique ID.
func (db *DynamoDB) SaveUser(u *models.User) error {
	if u.ID == "" {
		id, err := shortid.ID(64)
		if err != nil {
			return err
		}

		u.ID = id
	}

	item, err := dynamodbattribute.MarshalMap(u)
	if err != nil {
		return err
	}

	_, err = db.DB.PutItem(&dynamodb.PutItemInput{
		TableName: aws.String("users"),
		Item:      item,
	})
	if err != nil {
		return err
	}

	return nil
}