func ReceiveMessage(pq *pqueue.PQueue, sqsQuery *urlutils.SQSQuery) sqs_response.SQSResponse { pqCfg := pq.Config() opts := &ReceiveMessageOptions{ WaitTimeSeconds: pqCfg.PopWaitTimeout, VisibilityTimeout: pqCfg.PopLockTimeout, MaxNumberOfMessages: 1, Attributes: nil, MessageAttributes: nil, } paramsLen := len(sqsQuery.ParamsList) - 1 for i := 0; i < paramsLen; i += 2 { err := opts.Parse(sqsQuery.ParamsList[i], sqsQuery.ParamsList[i+1]) if err != nil { return err } } // All messages received from SQS must be locked. res := pq.Pop(opts.VisibilityTimeout, opts.WaitTimeSeconds, opts.MaxNumberOfMessages, true) if res.IsError() { e, _ := res.(error) return sqserr.InvalidParameterValueError(e.Error()) } m, _ := res.(*resp.MessagesResponse) items := m.GetItems() output := &ReceiveMessageResponse{} for _, item := range items { if msgResp := MakeMessageResponse(item, opts, sqsQuery); msgResp != nil { output.Message = append(output.Message, msgResp) } } return output }
func PushAMessage(pq *pqueue.PQueue, senderId string, paramList []string) sqs_response.SQSResponse { out := &MessageParams{ DelaySeconds: -1, MessageBody: "", } attrs, err := urlutils.ParseNNotationAttr("MessageAttribute.", paramList, out.Parse, NewReqQueueAttr) if err != nil { return err } attrsLen := len(attrs) outAttrs := make(map[string]*sqsmsg.UserAttribute) for i := 1; i <= attrsLen; i++ { a, ok := attrs[i] if !ok { return sqserr.InvalidParameterValueError("The request must contain non-empty message attribute name.") } reqMsgAttr, _ := a.(*ReqMsgAttr) sqs_err := validation.ValidateMessageAttrName(reqMsgAttr.Name) if sqs_err != nil { return sqs_err } sqs_err = validation.ValidateMessageAttrName(reqMsgAttr.DataType) if sqs_err != nil { return sqs_err } if reqMsgAttr.BinaryValue != "" && reqMsgAttr.StringValue != "" { return sqserr.InvalidParameterValueError( "Message attribute name '%s' has multiple values.", reqMsgAttr.Name) } if _, ok := outAttrs[reqMsgAttr.Name]; ok { return sqserr.InvalidParameterValueError( "Message attribute name '%s' already exists.", reqMsgAttr.Name) } if strings.HasPrefix(reqMsgAttr.DataType, "Number") { if _, err := strconv.Atoi(reqMsgAttr.StringValue); err != nil { return sqserr.InvalidParameterValueError( "Could not cast message attribute '%s' value to number.", reqMsgAttr.Name) } } if reqMsgAttr.BinaryValue != "" { if reqMsgAttr.DataType != "Binary" { return sqserr.InvalidParameterValueError( "The message attribute '%s' with type 'Binary' must use field 'Binary'", reqMsgAttr.Name) } outAttrs[reqMsgAttr.Name] = &sqsmsg.UserAttribute{ Type: reqMsgAttr.DataType, Value: reqMsgAttr.BinaryValue, } continue } if reqMsgAttr.StringValue != "" { if reqMsgAttr.DataType != "String" && reqMsgAttr.DataType != "Number" { return sqserr.InvalidParameterValueError( "The message attribute '%s' with type 'String' must use field 'String'", reqMsgAttr.Name) } outAttrs[reqMsgAttr.Name] = &sqsmsg.UserAttribute{ Type: reqMsgAttr.DataType, Value: reqMsgAttr.StringValue, } } } msgId := IdGen.RandId() if out.DelaySeconds < 0 { out.DelaySeconds = pq.Config().DeliveryDelay } else if out.DelaySeconds > conf.CFG_PQ.MaxDeliveryDelay { return sqserr.InvalidParameterValueError( "Delay secods must be between 0 and %d", conf.CFG_PQ.MaxDeliveryDelay/1000) } bodyMd5str := fmt.Sprintf("%x", md5.Sum(enc.UnsafeStringToBytes(out.MessageBody))) attrMd5 := CalcAttrMd5(outAttrs) msgPayload := sqsmsg.SQSMessagePayload{ UserAttributes: outAttrs, MD5OfMessageBody: bodyMd5str, MD5OfMessageAttributes: attrMd5, SenderId: senderId, SentTimestamp: strconv.FormatInt(utils.Uts(), 10), Payload: out.MessageBody, } d, marshalErr := msgPayload.Marshal() if marshalErr != nil { log.Error("Failed to serialize message payload: %v", err) } payload := enc.UnsafeBytesToString(d) resp := pq.Push(msgId, payload, pq.Config().MsgTtl, out.DelaySeconds, 1) if resp.IsError() { e, _ := resp.(error) return sqserr.InvalidParameterValueError(e.Error()) } return &SendMessageResponse{ MessageId: msgId, MD5OfMessageBody: bodyMd5str, MD5OfMessageAttributes: attrMd5, RequestId: "req", } }
func GetQueueAttributes(pq *pqueue.PQueue, sqsQuery *urlutils.SQSQuery) sqs_response.SQSResponse { paramsLen := len(sqsQuery.ParamsList) - 1 pqCfg := pq.Config() pqDesc := pq.Description() resp := &GetQueueAttributesResponse{ RequestId: "reqId", } for i := 0; i < paramsLen; i += 2 { allAttr := false if strings.HasPrefix(sqsQuery.ParamsList[i], "AttributeName") { attrName := sqsQuery.ParamsList[i+1] if attrName == AttrAll { allAttr = true resp.Attributes = make([]*QAttr, 0, 13) // 13 total attributes } if allAttr || attrName == AttrApproximateNumberOfMessages { resp.Attributes = append(resp.Attributes, &QAttr{ Name: AttrApproximateNumberOfMessages, Value: pq.AvailableMessages(), }) } if allAttr || attrName == AttrApproximateNumberOfMessagesNotVisible { resp.Attributes = append(resp.Attributes, &QAttr{ Name: AttrApproximateNumberOfMessagesNotVisible, Value: pq.LockedCount(), }) } if allAttr || attrName == AttrVisibilityTimeout { resp.Attributes = append(resp.Attributes, &QAttr{ Name: AttrVisibilityTimeout, Value: pqCfg.PopLockTimeout / 1000, }) } if allAttr || attrName == AttrCreatedTimestamp { resp.Attributes = append(resp.Attributes, &QAttr{ Name: AttrCreatedTimestamp, Value: pqDesc.CreateTs / 1000, }) } if allAttr || attrName == AttrLastModifiedTimestamp { resp.Attributes = append(resp.Attributes, &QAttr{ Name: AttrLastModifiedTimestamp, Value: pqCfg.LastUpdateTs / 1000, }) } if allAttr || attrName == AttrMaximumMessageSize { resp.Attributes = append(resp.Attributes, &QAttr{ Name: AttrMaximumMessageSize, Value: pqCfg.MaxMsgSize, }) } if allAttr || attrName == AttrMessageRetentionPeriod { resp.Attributes = append(resp.Attributes, &QAttr{ Name: AttrMessageRetentionPeriod, Value: pqCfg.MsgTtl / 1000, }) } if allAttr || attrName == AttrQueueArn { resp.Attributes = append(resp.Attributes, &QAttr{ Name: AttrQueueArn, Value: makeQueueArn(pqDesc.Name), }) } if allAttr || attrName == AttrApproximateNumberOfMessagesDelayed { resp.Attributes = append(resp.Attributes, &QAttr{ Name: AttrApproximateNumberOfMessagesDelayed, Value: pq.DelayedCount(), }) } if allAttr || attrName == AttrDelaySeconds { resp.Attributes = append(resp.Attributes, &QAttr{ Name: AttrDelaySeconds, Value: pqCfg.DeliveryDelay / 1000, }) } if allAttr || attrName == AttrReceiveMessageWaitTimeSeconds { resp.Attributes = append(resp.Attributes, &QAttr{ Name: AttrReceiveMessageWaitTimeSeconds, Value: pqCfg.PopWaitTimeout / 1000, }) } if allAttr || attrName == AttrRedrivePolicy { if pqCfg.PopLimitQueueName != "" { resp.Attributes = append(resp.Attributes, &QAttr{ Name: AttrRedrivePolicy, Value: fmt.Sprintf(`{"deadLetterTargetArn":"%s","maxReceiveCount":%d}`, makeQueueArn(pqCfg.PopLimitQueueName), pqCfg.PopCountLimit), }) } } if allAttr { break } } } return resp }