// query using LSI or GSI
func (t *DynamoTable) GetByIndex(idx string, values ...Any) ([]map[string]interface{}, error) {
	index, ok := t.indexes[idx]
	if !ok {
		log.Error("[DynamoDB] Cannot find the index name, table="+t.name, idx)
		log.Error("[DynamoDB] indexes on table="+t.name, t.indexes)
	}

	hashKey := index.GetHashKeyName()
	rangeKey := index.GetRangeKeyName()

	keys := make(map[string]*SDK.Condition)
	keys[hashKey] = &SDK.Condition{
		AttributeValueList: []*SDK.AttributeValue{createAttributeValue(values[0])},
		ComparisonOperator: String(ComparisonOperatorEQ),
	}
	if len(values) > 1 && rangeKey != "" {
		keys[rangeKey] = &SDK.Condition{
			AttributeValueList: []*SDK.AttributeValue{createAttributeValue(values[1])},
			ComparisonOperator: String(ComparisonOperatorEQ),
		}
	}

	in := &SDK.QueryInput{
		TableName:     String(t.name),
		KeyConditions: keys,
		IndexName:     &idx,
	}
	return t.Query(in)
}
// Send messages in the send spool
func (q *Queue) Send() error {
	// pack the messages ten each to meet the SQS restriction.
	messages := make(map[int][]*SDK.SendMessageBatchRequestEntry)
	if len(q.messages) > 10 {
		for i, msg := range q.messages {
			v := (i + 1) / 10
			messages[v] = append(messages[v], msg)
		}
	} else {
		messages[0] = append(messages[0], q.messages...)
	}

	err := &SQSError{}
	// send message
	for i := 0; i < len(messages); i++ {
		e := q.send(messages[i])
		if e != nil {
			log.Error("[SQS] error on `SendMessageBatch` operation, queue="+q.name, e.Error())
			err.AddMessage(e.Error())
		}
	}

	if err.HasError() {
		return err
	}
	return nil
}
// Get message from the queue with limit
func (q *Queue) Fetch(num int) ([]*Message, error) {
	// use long-polling for 1sec when to get multiple messages
	var wait int = 0
	if num > 1 {
		wait = 1
	}

	// receive message from server
	resp, err := q.client.ReceiveMessage(&SDK.ReceiveMessageInput{
		QueueUrl:            q.url,
		WaitTimeSeconds:     Long(wait),
		MaxNumberOfMessages: Long(num),
		VisibilityTimeout:   Long(defaultExpireSecond),
	})
	if err != nil {
		log.Error("[SQS] error on `ReceiveMessage` operation, queue="+q.name, err.Error())
	}

	var list []*Message
	if resp == nil || len(resp.Messages) == 0 {
		return list, err
	}

	// delete messages automatically
	if q.autoDel {
		q.AddDeleteList(resp.Messages)
		defer q.DeleteListItems()
	}

	for _, msg := range resp.Messages {
		list = append(list, NewMessage(msg))
	}

	return list, err
}
Exemple #4
0
// Send messages in the send spool
func (q *Queue) Send() error {
	// pack the messages ten each to meet the SQS restriction.
	messages := make(map[int][]*SDK.SendMessageBatchRequestEntry)
	if len(q.messages) > 10 {
		for i, msg := range q.messages {
			v := (i + 1) / 10
			messages[v] = append(messages[v], msg)
		}
	} else {
		messages[0] = append(messages[0], q.messages...)
	}

	var err error = nil
	errStr := ""
	// send message
	for i := 0; i < len(messages); i++ {
		e := q.send(messages[i])
		if e != nil {
			log.Error("[SQS] error on `SendMessageBatch` operation, queue="+q.name, e.Error())
			errStr = errStr + "," + e.Error()
		}
	}
	if errStr != "" {
		err = errors.New(errStr)
	}
	return err
}
Exemple #5
0
// Get message from the queue with limit
func (q *Queue) Fetch(num int) (*SDK.ReceiveMessageOutput, error) {
	// use long-polling for 1sec when to get multiple messages
	var wait int
	if num > 1 {
		wait = 1
	} else {
		wait = 0
	}

	// receive message from server
	resp, err := q.client.ReceiveMessage(&SDK.ReceiveMessageInput{
		QueueURL:            q.url,
		WaitTimeSeconds:     Long(wait),
		MaxNumberOfMessages: Long(num),
		VisibilityTimeout:   Long(defaultExpireSecond),
	})
	if err != nil {
		log.Error("[SQS] error on `ReceiveMessage` operation, queue="+q.name, err.Error())
	}

	// delete messages automatically
	if q.autoDel && len(resp.Messages) > 0 {
		q.AddDeleteList(resp.Messages)
		defer q.DeleteListItems()
	}

	return resp, err
}
// make sns message for Apple Push Notification Service
func composeMessageAPNS(msg string, opt map[string]interface{}) string {
	aps := make(map[string]interface{})
	aps[apnsKeyMessage] = msg

	aps[apnsKeySound] = "default"
	if v, ok := opt[apnsKeySound]; ok {
		aps[apnsKeySound] = v
	}

	if v, ok := opt[apnsKeyBadge]; ok {
		aps[apnsKeyBadge] = v
	}

	message := make(map[string]interface{})
	message["aps"] = aps
	for k, v := range opt {
		switch k {
		case apnsKeySound:
			continue
		case apnsKeyBadge:
			continue
		default:
			message[k] = v
		}
	}

	payload, err := json.Marshal(message)
	if err != nil {
		log.Error("[SNS] error on json.Marshal", err.Error())
	}
	return string(payload)
}
func (q *Query) AndLT(key string, val interface{}) {
	if _, ok := q.conditions[key]; ok {
		log.Error("[DynamoDB] only contain one condition per key, key="+key, val)
	}
	cond := newQueryCondition(key, val)
	cond.Condition = conditionLT
	q.conditions[key] = cond
}
// get mapped-items with Query operation
func (t *DynamoTable) Query(in *SDK.QueryInput) ([]map[string]interface{}, error) {
	req, err := t.db.client.Query(in)
	if err != nil {
		log.Error("[DynamoDB] Error in `Query` operation, table="+t.name, err)
		return nil, err
	}
	return t.convertItemsToMapArray(req.Items), nil
}
func (q *Query) AndBETWEEN(key string, from, to interface{}) {
	if _, ok := q.conditions[key]; ok {
		log.Error("[DynamoDB] only contain one condition per key, key="+key, from)
	}
	cond := newQueryCondition(key, from)
	cond.SubValue = to
	cond.Condition = conditionBETWEEN
	q.conditions[key] = cond
}
Exemple #10
0
// Create new DynamoDB table
func (d *AmazonDynamoDB) CreateTable(in *SDK.CreateTableInput) error {
	data, err := d.client.CreateTable(in)
	if err != nil {
		log.Error("[DynamoDB] Error on `CreateTable` operation, table="+*in.TableName, err)
		return err
	}
	log.Info("[DynamoDB] Complete CreateTable, table="+*in.TableName, data.TableDescription.TableStatus)
	return nil
}
// RegisterEndpointWithUserData creates endpoint(device) and CustomUserData to application
func (svc *AmazonSNS) RegisterEndpointWithUserData(device, token, userData string) (*SNSEndpoint, error) {
	app, err := svc.getApp(device)
	if err != nil {
		log.Error(err.Error(), token)
		return nil, err
	}
	app.SetUserData(userData)
	return app.CreateEndpoint(token)
}
// RegisterEndpoint creates endpoint(device) to application
func (svc *AmazonSNS) RegisterEndpoint(device, token string) (*SNSEndpoint, error) {
	app, err := svc.getApp(device)
	if err != nil {
		log.Error(err.Error(), token)
		return nil, err
	}

	return app.CreateEndpoint(token)
}
// Create new SQS Queue
func (svc *AmazonSQS) CreateQueue(in *SDK.CreateQueueInput) error {
	data, err := svc.client.CreateQueue(in)
	if err != nil {
		log.Error("[SQS] Error on `CreateQueue` operation, queue="+*in.QueueName, err)
		return err
	}
	log.Info("[SQS] Complete CreateQueue, queue="+*in.QueueName, *(data.QueueUrl))
	return nil
}
Exemple #14
0
// Add message spool from map data
func (q *Queue) AddMessageMap(message map[string]interface{}) error {
	msg, err := json.Marshal(message)
	if err != nil {
		log.Error("[SQS] error on `json.Marshal`, msg="+fmt.Sprint(msg), err.Error())
		return err
	}
	q.AddMessage(string(msg))
	return nil
}
// GetEndpoint
func (svc *AmazonSNS) GetEndpoint(arn string) (*SNSEndpoint, error) {
	in := &SDK.GetEndpointAttributesInput{
		EndpointArn: String(arn),
	}
	resp, err := svc.Client.GetEndpointAttributes(in)
	if err != nil {
		log.Error("[SNS] error on `GetEndpointAttributes` operation, arn="+arn, err.Error())
		return nil, err
	}
	attr := resp.Attributes
	ep := svc.NewApplicationEndpoint(arn)
	ep.token = *attr["Token"]
	ep.enable, err = strconv.ParseBool(*attr["Enabled"])
	if err != nil {
		log.Error("[SNS] error on `Endpoint Attributes` Enabled="+*attr["Enabled"], err.Error())
		ep.enable = false
	}
	return ep, err
}
func (t *DynamoTable) Desc() (*SDK.TableDescription, error) {
	req, err := t.db.client.DescribeTable(&SDK.DescribeTableInput{
		TableName: String(t.name),
	})
	if err != nil {
		log.Error("[DynamoDB] Error in `DescribeTable` operation, table="+t.name, err)
		return nil, err
	}
	return req.Table, nil
}
Exemple #17
0
// delete object of target path
func (b *Bucket) DeleteObject(path string) error {
	_, err := b.client.DeleteObject(&SDK.DeleteObjectInput{
		Bucket: String(b.name),
		Key:    String(path),
	})
	if err != nil {
		log.Error("[S3] error on `DeleteObject` operation, bucket="+b.name, err.Error())
	}
	return err
}
Exemple #18
0
// Delete all messages on the Queue
func (q *Queue) Purge() error {
	_, err := q.client.PurgeQueue(&SDK.PurgeQueueInput{
		QueueURL: q.url,
	})
	if err != nil {
		log.Error("[SQS] error on `PurgeQueue`, queue="+q.name, err.Error())
		return err
	}
	return nil
}
Exemple #19
0
// Delete a message from server
func (q *Queue) DeleteMessage(msg *SDK.Message) error {
	_, err := q.client.DeleteMessage(&SDK.DeleteMessageInput{
		QueueURL:      q.url,
		ReceiptHandle: msg.ReceiptHandle,
	})
	if err != nil {
		log.Error("[SQS] error on `DeleteMessage`, queue="+q.name, err.Error())
	}
	return err
}
// Create SNS Topic and return `TopicARN`
func (svc *AmazonSNS) createTopic(name string) (string, error) {
	prefix := config.GetConfigValue(snsConfigSectionName, "prefix", defaultPrefix)
	in := &SDK.CreateTopicInput{
		Name: String(prefix + name),
	}
	resp, err := svc.Client.CreateTopic(in)
	if err != nil {
		log.Error("[SNS] error on `CreateTopic` operation, name="+name, err.Error())
		return "", err
	}
	return *resp.TopicArn, nil
}
Exemple #21
0
// Delete DynamoDB table
func (d *AmazonDynamoDB) DeleteTable(name string) error {
	in := &SDK.DeleteTableInput{
		TableName: String(name),
	}
	data, err := d.client.DeleteTable(in)
	if err != nil {
		log.Error("[DynamoDB] Error on `DeleteTable` operation, table="+*in.TableName, err)
		return err
	}
	log.Info("[DynamoDB] Complete DeleteTable, table="+*in.TableName, data.TableDescription.TableStatus)
	return nil
}
Exemple #22
0
// fetch object from target S3 path
func (b *Bucket) getObject(path string) (io.Reader, error) {
	req := SDK.GetObjectInput{
		Bucket: &b.name,
		Key:    &path,
	}
	out, err := b.client.GetObject(&req)
	if err != nil {
		log.Error("[S3] error on `GetObject` operation, bucket="+b.name, err.Error())
		return nil, err
	}
	return out.Body, err
}
// Subscribe
func (t *SNSTopic) Subscribe(endpoint *SNSEndpoint) (string, error) {
	resp, err := t.svc.Client.Subscribe(&SDK.SubscribeInput{
		Endpoint: String(endpoint.arn),
		Protocol: String(endpoint.protocol),
		TopicARN: String(t.arn),
	})
	if err != nil {
		log.Error("[SNS] error on `Subscribe` operation, topic="+t.arn, err.Error())
		return "", err
	}
	return *resp.SubscriptionARN, nil
}
// get mapped-items with Scan operation
func (t *DynamoTable) Scan() ([]map[string]interface{}, error) {
	in := &SDK.ScanInput{
		TableName: String(t.name),
		Limit:     Long(1000),
	}
	req, err := t.db.client.Scan(in)
	if err != nil {
		log.Error("[DynamoDB] Error in `Scan` operation, table="+t.name, err)
		return nil, err
	}
	return t.convertItemsToMapArray(req.Items), nil
}
Exemple #25
0
// Create Endpoint(add device) and return `EndpointARN`
func (a *SNSApp) createEndpoint(token string) (string, error) {
	in := &SDK.CreatePlatformEndpointInput{
		PlatformApplicationARN: String(a.arn),
		Token: String(token),
	}
	resp, err := a.svc.Client.CreatePlatformEndpoint(in)
	if err != nil {
		log.Error("[SNS] error on `CreatePlatformEndpoint` operation, token="+token, err.Error())
		return "", err
	}
	return *resp.EndpointARN, nil
}
func (ct *CreateTableInput) addGSI(name string, key ...string) {
	var schema []*SDK.KeySchemaElement
	switch len(key) {
	case 1:
		schema = NewKeySchema(NewHashKeyElement(key[0]))
	case 2:
		schema = NewKeySchema(NewHashKeyElement(key[0]), NewRangeKeyElement(key[1]))
	default:
		log.Error("[DynamoDB] keys must have 1 or 2, name="+name, len(key))
		return
	}
	tp := NewProvisionedThroughput(ct.ReadCapacity, ct.WriteCapacity)
	gsi := NewGSI(name, schema, tp)
	ct.GSI = append(ct.GSI, gsi)
}
Exemple #27
0
// execute put operation for all tables in write spool
func (d *AmazonDynamoDB) PutAll() error {
	var errs []string
	for name, _ := range d.writeTables {
		err := d.tables[name].Put()
		if err != nil {
			errs = append(errs, err.Error())
			log.Error("[DynamoDB] Error on `Put` operation, table="+name, err.Error())
		}
		d.removeWriteTable(name)
	}
	if len(errs) != 0 {
		return errors.New(strings.Join(errs, "\n"))
	}
	return nil
}
Exemple #28
0
// Delete a packed message
func (q *Queue) delete(msg []*SDK.DeleteMessageBatchRequestEntry) error {
	if len(msg) < 1 {
		return nil
	}
	res, err := q.client.DeleteMessageBatch(&SDK.DeleteMessageBatchInput{
		Entries:  msg,
		QueueURL: q.url,
	})
	if err != nil {
		log.Error("[SQS] error on `DeleteMessageBatch`, queue="+q.name, err.Error())
		q.failedDelete = append(q.failedDelete, res.Failed...)
	}

	return err
}
// updateThroughput updates dynamodb table provisioned throughput
func (t *DynamoTable) updateThroughput(in *SDK.UpdateTableInput) error {
	if t.isSameThroughput(in) {
		return nil
	}
	_, err := t.db.client.UpdateTable(in)
	if err != nil {
		log.Error("[DynamoDB] Error in `UpdateTable` operation, table="+t.name, err)
		return err
	}
	desc, err := t.Desc()
	if err != nil {
		return err
	}
	t.table = desc
	return nil
}
func (q *Query) query(in *SDK.QueryInput) (*QueryResult, error) {
	if !q.HasCondition() {
		errData := &DynamoError{}
		errData.AddMessage("condition is missing, you must specify at least one condition")
		return nil, errData
	}
	in.KeyConditionExpression = q.formatConditions()
	in.ExpressionAttributeValues = q.formatConditionValues()
	in.ExpressionAttributeNames = q.formatConditionNames()

	if q.HasIndex() {
		in.IndexName = String(q.index)
	}
	if q.HasLimit() {
		in.Limit = Long(q.limit)
	}

	req, err := q.table.db.client.Query(in)
	if err != nil {
		log.Error("[DynamoDB] Error in `Query` operation, table="+q.table.name, err)
		return nil, err
	}

	res := &QueryResult{
		Items:            req.Items,
		LastEvaluatedKey: req.LastEvaluatedKey,
		Count:            *req.Count,
		ScannedCount:     *req.ScannedCount,
	}
	return res, nil
}