11
11
use Aws \Sqs \SqsClient ;
12
12
use yii \base \NotSupportedException ;
13
13
use yii \queue \cli \Queue as CliQueue ;
14
+ use yii \queue \serializers \JsonSerializer ;
14
15
15
16
/**
16
17
* SQS Queue.
@@ -52,8 +53,14 @@ class Queue extends CliQueue
52
53
53
54
/**
54
55
* @var string command class name
56
+ * @inheritdoc
55
57
*/
56
58
public $ commandClass = Command::class;
59
+ /**
60
+ * Json serializer by default.
61
+ * @inheritdoc
62
+ */
63
+ public $ serializer = JsonSerializer::class;
57
64
58
65
/**
59
66
* @var SqsClient
@@ -80,12 +87,12 @@ public function run($repeat, $timeout = 0)
80
87
{
81
88
return $ this ->runWorker (function (callable $ canContinue ) use ($ repeat , $ timeout ) {
82
89
while ($ canContinue ()) {
83
- if (($ payload = $ this ->getPayload ($ timeout )) !== null ) {
84
- list ( $ ttr , $ message ) = explode ( ' ; ' , base64_decode ( $ payload ['Body ' ]), 2 ) ;
85
- //reserve it so it is not visible to another worker till ttr
86
- $ this -> reserve ( $ payload , $ ttr ) ;
87
-
88
- if ($ this ->handleMessage (null , $ message , $ ttr , 1 )) {
90
+ if (($ payload = $ this ->reserve ($ timeout )) !== null ) {
91
+ $ id = $ payload ['MessageId ' ] ;
92
+ $ message = $ payload [ ' Body ' ];
93
+ $ ttr = ( int ) $ payload [ ' MessageAttributes ' ][ ' TTR ' ][ ' StringValue ' ] ;
94
+ $ attempt = ( int ) $ payload [ ' Attributes ' ][ ' ApproximateReceiveCount ' ];
95
+ if ($ this ->handleMessage ($ id , $ message , $ ttr , $ attempt )) {
89
96
$ this ->release ($ payload );
90
97
}
91
98
} elseif (!$ repeat ) {
@@ -96,64 +103,50 @@ public function run($repeat, $timeout = 0)
96
103
}
97
104
98
105
/**
99
- * Gets a single message from SQS queue.
106
+ * Gets a single message from SQS queue and sets the visibility to reserve message .
100
107
*
101
108
* @param int $timeout number of seconds for long polling. Must be between 0 and 20.
102
109
* @return null|array payload.
103
110
*/
104
- private function getPayload ($ timeout = 0 )
111
+ public function reserve ($ timeout )
105
112
{
106
- $ payload = $ this ->getClient ()->receiveMessage ([
113
+ $ response = $ this ->getClient ()->receiveMessage ([
107
114
'QueueUrl ' => $ this ->url ,
108
115
'AttributeNames ' => ['ApproximateReceiveCount ' ],
116
+ 'MessageAttributeNames ' => ['TTR ' ],
109
117
'MaxNumberOfMessages ' => 1 ,
118
+ 'VisibilityTimeout ' => $ this ->ttr ,
110
119
'WaitTimeSeconds ' => $ timeout ,
111
120
]);
112
-
113
- $ payload = $ payload ['Messages ' ];
114
- if ($ payload ) {
115
- return array_pop ($ payload );
121
+ if (!$ response ['Messages ' ]) {
122
+ return null ;
116
123
}
117
124
118
- return null ;
119
- }
125
+ $ payload = reset ($ response ['Messages ' ]);
120
126
121
- /**
122
- * Set the visibility to reserve message.
123
- * So that no other worker can see this message.
124
- *
125
- * @param array $payload
126
- * @param int $ttr
127
- */
128
- private function reserve ($ payload , $ ttr )
129
- {
130
- $ receiptHandle = $ payload ['ReceiptHandle ' ];
131
- $ this ->getClient ()->changeMessageVisibility ([
132
- 'QueueUrl ' => $ this ->url ,
133
- 'ReceiptHandle ' => $ receiptHandle ,
134
- 'VisibilityTimeout ' => $ ttr ,
135
- ]);
127
+ $ ttr = (int ) $ payload ['MessageAttributes ' ]['TTR ' ]['StringValue ' ];
128
+ if ($ ttr != $ this ->ttr ) {
129
+ $ this ->getClient ()->changeMessageVisibility ([
130
+ 'QueueUrl ' => $ this ->url ,
131
+ 'ReceiptHandle ' => $ payload ['ReceiptHandle ' ],
132
+ 'VisibilityTimeout ' => $ ttr ,
133
+ ]);
134
+ }
135
+
136
+ return $ payload ;
136
137
}
137
138
138
139
/**
139
140
* Mark the message as handled.
140
141
*
141
142
* @param array $payload
142
- * @return bool
143
143
*/
144
144
private function release ($ payload )
145
145
{
146
- if (empty ($ payload ['ReceiptHandle ' ])) {
147
- return false ;
148
- }
149
-
150
- $ receiptHandle = $ payload ['ReceiptHandle ' ];
151
- $ response = $ this ->getClient ()->deleteMessage ([
146
+ $ this ->getClient ()->deleteMessage ([
152
147
'QueueUrl ' => $ this ->url ,
153
- 'ReceiptHandle ' => $ receiptHandle ,
148
+ 'ReceiptHandle ' => $ payload [ ' ReceiptHandle ' ] ,
154
149
]);
155
-
156
- return $ response !== null ;
157
150
}
158
151
159
152
/**
@@ -183,13 +176,18 @@ protected function pushMessage($message, $ttr, $delay, $priority)
183
176
throw new NotSupportedException ('Priority is not supported in this driver ' );
184
177
}
185
178
186
- $ model = $ this ->getClient ()->sendMessage ([
187
- 'DelaySeconds ' => $ delay ,
179
+ $ response = $ this ->getClient ()->sendMessage ([
188
180
'QueueUrl ' => $ this ->url ,
189
- 'MessageBody ' => base64_encode ("$ ttr; $ message " ),
181
+ 'MessageBody ' => $ message ,
182
+ 'DelaySeconds ' => $ delay ,
183
+ 'MessageAttributes ' => [
184
+ 'TTR ' => [
185
+ 'DataType ' => 'Number ' ,
186
+ 'StringValue ' => $ ttr ,
187
+ ],
188
+ ],
190
189
]);
191
-
192
- return $ model ['MessageId ' ];
190
+ return $ response ['MessageId ' ];
193
191
}
194
192
195
193
/**
@@ -211,22 +209,12 @@ protected function getClient()
211
209
//see - http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/credentials.html#credential-profiles
212
210
$ credentials = CredentialProvider::defaultProvider ();
213
211
}
212
+
214
213
$ this ->_client = new SqsClient ([
215
214
'credentials ' => $ credentials ,
216
215
'region ' => $ this ->region ,
217
216
'version ' => $ this ->version ,
218
217
]);
219
-
220
218
return $ this ->_client ;
221
219
}
222
-
223
- /**
224
- * Sets the AWS SQS client instance for the queue.
225
- *
226
- * @param SqsClient $client AWS SQS client object.
227
- */
228
- public function setClient (SqsClient $ client )
229
- {
230
- $ this ->_client = $ client ;
231
- }
232
220
}
0 commit comments