Example #1
0
func TestDynamoBasic(t *testing.T) {
	ctx := core.NewContext("test")

	ddb, err := NewStorage(ctx, testConfig)
	if noConnection(err) {
		t.Skip()
	}

	if err != nil {
		t.Fatal(err)
	}
	server := ddb.server

	{
		tables, err := server.ListTables()
		if err != nil {
			t.Fatal(err)
		}

		for _, t := range tables {
			log.Println("table " + t)
		}
	}

	table := ddb.table

	{
		attrs := []dynamodb.Attribute{
			*dynamodb.NewStringAttribute("likes", "beer"),
		}

		if ok, err := table.PutItem("homer", "", attrs); !ok {
			t.Fatal(err)
		}
	}

	{
		attrs := []dynamodb.Attribute{
			*dynamodb.NewStringAttribute("likes", "tacos"),
		}

		k := dynamodb.Key{HashKey: "homer"}
		if ok, err := table.UpdateAttributes(&k, attrs); !ok {
			t.Fatal(err)
		}
	}

	{
		k := dynamodb.Key{HashKey: "homer"}
		as, err := table.GetItem(&k)
		if err != nil {
			t.Fatal(err)
		}
		for _, v := range as {
			log.Println(v)
		}
	}
}
Example #2
0
// Remove removes the given data from DynamoDB.
//
// If 'CheckLastUpdated' is true, this function attempts to verify
// that the state in DynamoDB hasn't changed since we last loaded it
// or changed it.  If the state has changed unexpectedly, you get an
// error (which should be ConcurrentStateChange, but currently is just
// the error returned by the SDK).
func (s *DynamoDBStorage) Remove(ctx *Context, loc string, id []byte) (int64, error) {
	Log(INFO, ctx, "DynamoDBStorage.Remove", "location", loc, "id", string(id))

	lastUpdated, updating := ctx.Location().Update(ctx, "")
	Log(DEBUG, ctx, "DynamoDBStorage.Add", "location", loc, "lastUpdated", lastUpdated, "updatingAt", updating)

	attrs := []dynamodb.Attribute{
		*dynamodb.NewStringAttribute(string(id), ""),
		*dynamodb.NewStringAttribute(LastUpdatedKey, updating),
	}
	k := dynamodb.Key{HashKey: loc}

	var err error
	n := int64(1)
	var ok bool
	if CheckLastUpdated {
		// See comments elsewhere near CheckLastUpdated uses.
		update := dynamodb.Expression{
			Text: "REMOVE #a SET #u = :u",
			AttributeNames: map[string]string{
				"#a": string(id),
				"#u": lastUpdated,
			},
			AttributeValues: []dynamodb.Attribute{
				*dynamodb.NewStringAttribute(":u", updating),
			},
		}
		var cond dynamodb.Expression
		if lastUpdated == "" {
			cond = dynamodb.Expression{
				Text: "attribute_not_exists(#u)",
				AttributeNames: map[string]string{
					"#u": LastUpdatedKey,
				},
			}
		} else {
			cond = dynamodb.Expression{
				Text: "#u = :v",
				AttributeNames: map[string]string{
					"#u": LastUpdatedKey,
				},
				AttributeValues: []dynamodb.Attribute{
					*dynamodb.NewStringAttribute(":v", lastUpdated),
				},
			}
		}
		ok, err = s.table.UpdateExpressionUpdateAttributes(&k, &cond, &update)
	} else {
		ok, err = s.table.DeleteAttributes(&k, attrs)
	}
	if !ok {
		n = 0
	}
	return n, err
}
Example #3
0
// Add writes the given additional state to DynamoDB.
//
// If 'CheckLastUpdated' is true, this function attempts to verify
// that the state in DynamoDB hasn't changed since we last loaded it
// or changed it.  If the state has changed unexpectedly, you get an
// error (which should be ConcurrentStateChange, but currently is just
// the error returned by the SDK).
func (s *DynamoDBStorage) Add(ctx *Context, loc string, m *Pair) error {
	Log(INFO, ctx, "DynamoDBStorage.Add", "location", loc, "m", m.String())

	lastUpdated, updating := ctx.Location().Update(ctx, "")
	Log(DEBUG, ctx, "DynamoDBStorage.Add", "location", loc, "lastUpdated", lastUpdated, "updatingAt", updating)

	attrs := []dynamodb.Attribute{
		*dynamodb.NewStringAttribute(string(m.K), string(m.V)),
		*dynamodb.NewStringAttribute(LastUpdatedKey, updating),
	}
	k := dynamodb.Key{HashKey: loc}

	var err error
	var ok bool
	if CheckLastUpdated {
		// Maybe retry a little to see if we get the state we expect?
		// Probably no point, so don't actually loop.
		for i := 0; i < 1; i++ {
			// Ugh: "ExpressionAttributeValues contains invalid
			// value: One or more parameter values were invalid:
			// An AttributeValue may not contain an empty string
			// for key :Expected0."
			if lastUpdated == "" {
				cond := dynamodb.Expression{
					Text: "attribute_not_exists(#u)",
					AttributeNames: map[string]string{
						"#u": LastUpdatedKey,
					},
				}
				ok, err = s.table.ConditionExpressionUpdateAttributes(&k, attrs, &cond)
			} else {
				expected := []dynamodb.Attribute{
					*dynamodb.NewStringAttribute(LastUpdatedKey, lastUpdated),
				}
				ok, err = s.table.ConditionalUpdateAttributes(&k, attrs, expected)
			}
			if !ConditionalCheckFailedException(err) {
				break
			}
			// s.peek(ctx, loc)
			Log(WARN, ctx, "DynamoDBStorage.Add", "location", loc, "error", err, "retry", i)
			time.Sleep(10 * time.Millisecond)
		}
	} else {
		ok, err = s.table.UpdateAttributes(&k, attrs)
	}

	if err != nil {
		Log(WARN, ctx, "DynamoDBStorage.Add", "location", loc, "error", err, "ok", ok)
		return err
	}
	return nil
}
Example #4
0
func (r *MikroAdapter) Register(service *bridge.Service) error {
	attrs := []dynamodb.Attribute{
		//*dynamodb.NewStringAttribute("InstanceID", instanceId),
		*dynamodb.NewStringAttribute("HostAddr", service.IP),
		*dynamodb.NewNumericAttribute("HostPort", strconv.Itoa(service.Port)),
		*dynamodb.NewStringAttribute("ExpiresAt", time.Now().Add(
			time.Second*time.Duration(service.TTL)).Format(time.RFC3339)),
		*dynamodb.NewStringAttribute("UpdatedAt", time.Now().Format(time.RFC3339)),
	}

	ok, err := r.table.PutItem(service.Name, service.ID, attrs)
	if !ok {
		log.Println("mikro: failed to register service:", err)
	}
	return err
}
Example #5
0
// init creates the given table if it doesn't exist.
func (s *DynamoDBStorage) init(ctx *Context, table string) error {
	Log(INFO, ctx, "DynamoDBStorage.init", "table", table)
	td, err := s.server.DescribeTable(table)
	if err != nil {
		Log(INFO, ctx, "DynamoDBStorage.init", "creating", table)
		td = dynamodbTableDescription(table)
		_, err = s.server.CreateTable(*td)
		if err != nil {
			Log(INFO, ctx, "DynamoDBStorage.init", "error", err)
			return err
		}
	}
	Log(INFO, ctx, "DynamoDBStorage.init", "td", td)

	pk, err := td.BuildPrimaryKey()
	if err != nil {
		panic(err)
	}
	if pk.KeyAttribute == nil {
		// Puslar issue?
		name := td.AttributeDefinitions[0].Name
		attr := dynamodb.NewStringAttribute(name, "")
		attr.Type = td.AttributeDefinitions[0].Type
		pk.KeyAttribute = attr
		Log(INFO, ctx, "DynamoDBStorage.init", "pulsar", *pk.KeyAttribute)
	}
	s.table = s.server.NewTable(table, pk)
	return nil
}
Example #6
0
func (s *DynamoDBStorage) Clear(ctx *Context, loc string) (int64, error) {
	Log(INFO, ctx, "DynamoDBStorage.Clear", "location", loc)

	lastUpdated, updating := ctx.Location().Update(ctx, "clear")
	Log(DEBUG, ctx, "DynamoDBStorage.Clear", "location", loc, "lastUpdated", lastUpdated, "updatingAt", updating)

	k := dynamodb.Key{HashKey: loc}
	var ok bool
	var err error
	n := int64(0)
	if CheckLastUpdated && lastUpdated != "" {
		// See comments elsewhere near CheckLastUpdated uses.
		cond := []dynamodb.Attribute{
			*dynamodb.NewStringAttribute(LastUpdatedKey, lastUpdated),
		}
		ok, err = s.table.ConditionalDeleteItem(&k, cond)
	} else {
		ok, err = s.table.DeleteItem(&k)
	}
	if ok {
		n = 1
	}
	return n, err
}