Skip to content

Commit cf6e6d0

Browse files
authored
[DynamoDb] Adding BatchGetItem (#677)
* [DynamoDb] Adding BatchGetItem * Bugfix * Test fixes * cs * Fixed tests * Generate * Introduce "parserResult" * cs * Added return type hints to the anonymous functions * minor * Updated baseline
1 parent 83956d5 commit cf6e6d0

14 files changed

+752
-0
lines changed

src/DynamoDbClient.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use AsyncAws\Core\Configuration;
77
use AsyncAws\Core\Exception\UnsupportedRegion;
88
use AsyncAws\Core\RequestContext;
9+
use AsyncAws\DynamoDb\Input\BatchGetItemInput;
910
use AsyncAws\DynamoDb\Input\CreateTableInput;
1011
use AsyncAws\DynamoDb\Input\DeleteItemInput;
1112
use AsyncAws\DynamoDb\Input\DeleteTableInput;
@@ -18,6 +19,7 @@
1819
use AsyncAws\DynamoDb\Input\UpdateItemInput;
1920
use AsyncAws\DynamoDb\Input\UpdateTableInput;
2021
use AsyncAws\DynamoDb\Input\UpdateTimeToLiveInput;
22+
use AsyncAws\DynamoDb\Result\BatchGetItemOutput;
2123
use AsyncAws\DynamoDb\Result\CreateTableOutput;
2224
use AsyncAws\DynamoDb\Result\DeleteItemOutput;
2325
use AsyncAws\DynamoDb\Result\DeleteTableOutput;
@@ -35,6 +37,26 @@
3537

3638
class DynamoDbClient extends AbstractApi
3739
{
40+
/**
41+
* The `BatchGetItem` operation returns the attributes of one or more items from one or more tables. You identify
42+
* requested items by primary key.
43+
*
44+
* @see https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#batchgetitem
45+
*
46+
* @param array{
47+
* RequestItems: array<string, \AsyncAws\DynamoDb\ValueObject\KeysAndAttributes>,
48+
* ReturnConsumedCapacity?: \AsyncAws\DynamoDb\Enum\ReturnConsumedCapacity::*,
49+
* @region?: string,
50+
* }|BatchGetItemInput $input
51+
*/
52+
public function batchGetItem($input): BatchGetItemOutput
53+
{
54+
$input = BatchGetItemInput::create($input);
55+
$response = $this->getResponse($input->request(), new RequestContext(['operation' => 'BatchGetItem', 'region' => $input->getRegion()]));
56+
57+
return new BatchGetItemOutput($response, $this, $input);
58+
}
59+
3860
/**
3961
* The `CreateTable` operation adds a new table to your account. In an AWS account, table names must be unique within
4062
* each Region. That is, you can have two tables with same name if you create the tables in different Regions.

src/Input/BatchGetItemInput.php

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<?php
2+
3+
namespace AsyncAws\DynamoDb\Input;
4+
5+
use AsyncAws\Core\Exception\InvalidArgument;
6+
use AsyncAws\Core\Input;
7+
use AsyncAws\Core\Request;
8+
use AsyncAws\Core\Stream\StreamFactory;
9+
use AsyncAws\DynamoDb\Enum\ReturnConsumedCapacity;
10+
use AsyncAws\DynamoDb\ValueObject\KeysAndAttributes;
11+
12+
final class BatchGetItemInput extends Input
13+
{
14+
/**
15+
* A map of one or more table names and, for each table, a map that describes one or more items to retrieve from that
16+
* table. Each table name can be used only once per `BatchGetItem` request.
17+
*
18+
* @required
19+
*
20+
* @var array<string, KeysAndAttributes>
21+
*/
22+
private $RequestItems;
23+
24+
/**
25+
* @var null|ReturnConsumedCapacity::*
26+
*/
27+
private $ReturnConsumedCapacity;
28+
29+
/**
30+
* @param array{
31+
* RequestItems?: array<string, \AsyncAws\DynamoDb\ValueObject\KeysAndAttributes>,
32+
* ReturnConsumedCapacity?: \AsyncAws\DynamoDb\Enum\ReturnConsumedCapacity::*,
33+
* @region?: string,
34+
* } $input
35+
*/
36+
public function __construct(array $input = [])
37+
{
38+
$this->RequestItems = [];
39+
foreach ($input['RequestItems'] ?? [] as $key => $item) {
40+
$this->RequestItems[$key] = KeysAndAttributes::create($item);
41+
}
42+
$this->ReturnConsumedCapacity = $input['ReturnConsumedCapacity'] ?? null;
43+
parent::__construct($input);
44+
}
45+
46+
public static function create($input): self
47+
{
48+
return $input instanceof self ? $input : new self($input);
49+
}
50+
51+
/**
52+
* @return array<string, KeysAndAttributes>
53+
*/
54+
public function getRequestItems(): array
55+
{
56+
return $this->RequestItems;
57+
}
58+
59+
/**
60+
* @return ReturnConsumedCapacity::*|null
61+
*/
62+
public function getReturnConsumedCapacity(): ?string
63+
{
64+
return $this->ReturnConsumedCapacity;
65+
}
66+
67+
/**
68+
* @internal
69+
*/
70+
public function request(): Request
71+
{
72+
// Prepare headers
73+
$headers = [
74+
'Content-Type' => 'application/x-amz-json-1.0',
75+
'X-Amz-Target' => 'DynamoDB_20120810.BatchGetItem',
76+
];
77+
78+
// Prepare query
79+
$query = [];
80+
81+
// Prepare URI
82+
$uriString = '/';
83+
84+
// Prepare Body
85+
$bodyPayload = $this->requestBody();
86+
$body = empty($bodyPayload) ? '{}' : json_encode($bodyPayload);
87+
88+
// Return the Request
89+
return new Request('POST', $uriString, $query, $headers, StreamFactory::create($body));
90+
}
91+
92+
/**
93+
* @param array<string, KeysAndAttributes> $value
94+
*/
95+
public function setRequestItems(array $value): self
96+
{
97+
$this->RequestItems = $value;
98+
99+
return $this;
100+
}
101+
102+
/**
103+
* @param ReturnConsumedCapacity::*|null $value
104+
*/
105+
public function setReturnConsumedCapacity(?string $value): self
106+
{
107+
$this->ReturnConsumedCapacity = $value;
108+
109+
return $this;
110+
}
111+
112+
private function requestBody(): array
113+
{
114+
$payload = [];
115+
116+
foreach ($this->RequestItems as $name => $v) {
117+
$payload['RequestItems'][$name] = $v->requestBody();
118+
}
119+
if (null !== $v = $this->ReturnConsumedCapacity) {
120+
if (!ReturnConsumedCapacity::exists($v)) {
121+
throw new InvalidArgument(sprintf('Invalid parameter "ReturnConsumedCapacity" for "%s". The value "%s" is not a valid "ReturnConsumedCapacity".', __CLASS__, $v));
122+
}
123+
$payload['ReturnConsumedCapacity'] = $v;
124+
}
125+
126+
return $payload;
127+
}
128+
}

src/Result/BatchGetItemOutput.php

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
<?php
2+
3+
namespace AsyncAws\DynamoDb\Result;
4+
5+
use AsyncAws\Core\Response;
6+
use AsyncAws\Core\Result;
7+
use AsyncAws\DynamoDb\DynamoDbClient;
8+
use AsyncAws\DynamoDb\Input\BatchGetItemInput;
9+
use AsyncAws\DynamoDb\ValueObject\AttributeValue;
10+
use AsyncAws\DynamoDb\ValueObject\Capacity;
11+
use AsyncAws\DynamoDb\ValueObject\ConsumedCapacity;
12+
use AsyncAws\DynamoDb\ValueObject\KeysAndAttributes;
13+
14+
/**
15+
* @implements \IteratorAggregate<ConsumedCapacity>
16+
*/
17+
class BatchGetItemOutput extends Result implements \IteratorAggregate
18+
{
19+
/**
20+
* A map of table name to a list of items. Each object in `Responses` consists of a table name, along with a map of
21+
* attribute data consisting of the data type and attribute value.
22+
*/
23+
private $Responses = [];
24+
25+
/**
26+
* A map of tables and their respective keys that were not processed with the current response. The `UnprocessedKeys`
27+
* value is in the same form as `RequestItems`, so the value can be provided directly to a subsequent `BatchGetItem`
28+
* operation. For more information, see `RequestItems` in the Request Parameters section.
29+
*/
30+
private $UnprocessedKeys = [];
31+
32+
/**
33+
* The read capacity units consumed by the entire `BatchGetItem` operation.
34+
*/
35+
private $ConsumedCapacity = [];
36+
37+
/**
38+
* @param bool $currentPageOnly When true, iterates over items of the current page. Otherwise also fetch items in the next pages.
39+
*
40+
* @return iterable<ConsumedCapacity>
41+
*/
42+
public function getConsumedCapacity(bool $currentPageOnly = false): iterable
43+
{
44+
if ($currentPageOnly) {
45+
$this->initialize();
46+
yield from $this->ConsumedCapacity;
47+
48+
return;
49+
}
50+
51+
$client = $this->awsClient;
52+
if (!$client instanceof DynamoDbClient) {
53+
throw new \InvalidArgumentException('missing client injected in paginated result');
54+
}
55+
if (!$this->input instanceof BatchGetItemInput) {
56+
throw new \InvalidArgumentException('missing last request injected in paginated result');
57+
}
58+
$input = clone $this->input;
59+
$page = $this;
60+
while (true) {
61+
if ($page->getUnprocessedKeys()) {
62+
$input->setRequestItems($page->getUnprocessedKeys());
63+
64+
$this->registerPrefetch($nextPage = $client->BatchGetItem($input));
65+
} else {
66+
$nextPage = null;
67+
}
68+
69+
yield from $page->getConsumedCapacity(true);
70+
71+
if (null === $nextPage) {
72+
break;
73+
}
74+
75+
$this->unregisterPrefetch($nextPage);
76+
$page = $nextPage;
77+
}
78+
}
79+
80+
/**
81+
* Iterates over ConsumedCapacity.
82+
*
83+
* @return \Traversable<ConsumedCapacity>
84+
*/
85+
public function getIterator(): \Traversable
86+
{
87+
$client = $this->awsClient;
88+
if (!$client instanceof DynamoDbClient) {
89+
throw new \InvalidArgumentException('missing client injected in paginated result');
90+
}
91+
if (!$this->input instanceof BatchGetItemInput) {
92+
throw new \InvalidArgumentException('missing last request injected in paginated result');
93+
}
94+
$input = clone $this->input;
95+
$page = $this;
96+
while (true) {
97+
if ($page->getUnprocessedKeys()) {
98+
$input->setRequestItems($page->getUnprocessedKeys());
99+
100+
$this->registerPrefetch($nextPage = $client->BatchGetItem($input));
101+
} else {
102+
$nextPage = null;
103+
}
104+
105+
yield from $page->getConsumedCapacity(true);
106+
107+
if (null === $nextPage) {
108+
break;
109+
}
110+
111+
$this->unregisterPrefetch($nextPage);
112+
$page = $nextPage;
113+
}
114+
}
115+
116+
/**
117+
* @return array<string, array>
118+
*/
119+
public function getResponses(): array
120+
{
121+
$this->initialize();
122+
123+
return $this->Responses;
124+
}
125+
126+
/**
127+
* @return array<string, KeysAndAttributes>
128+
*/
129+
public function getUnprocessedKeys(): array
130+
{
131+
$this->initialize();
132+
133+
return $this->UnprocessedKeys;
134+
}
135+
136+
protected function populateResult(Response $response): void
137+
{
138+
$data = $response->toArray();
139+
$fn = [];
140+
$fn['list-ItemList'] = static function (array $json) use (&$fn): array {
141+
$items = [];
142+
foreach ($json as $item) {
143+
$a = empty($item) ? [] : $fn['map-AttributeMap']($item);
144+
if (null !== $a) {
145+
$items[] = $a;
146+
}
147+
}
148+
149+
return $items;
150+
};
151+
152+
/** @return array<string, \AsyncAws\DynamoDb\ValueObject\AttributeValue> */
153+
$fn['map-AttributeMap'] = static function (array $json): array {
154+
$items = [];
155+
foreach ($json as $name => $value) {
156+
$items[(string) $name] = AttributeValue::create($value);
157+
}
158+
159+
return $items;
160+
};
161+
162+
/** @return array<string, \AsyncAws\DynamoDb\ValueObject\KeysAndAttributes> */
163+
$fn['map-BatchGetRequestMap'] = static function (array $json): array {
164+
$items = [];
165+
foreach ($json as $name => $value) {
166+
$items[(string) $name] = KeysAndAttributes::create($value);
167+
}
168+
169+
return $items;
170+
};
171+
$fn['list-ConsumedCapacityMultiple'] = static function (array $json) use (&$fn): array {
172+
$items = [];
173+
foreach ($json as $item) {
174+
$items[] = new ConsumedCapacity([
175+
'TableName' => isset($item['TableName']) ? (string) $item['TableName'] : null,
176+
'CapacityUnits' => isset($item['CapacityUnits']) ? (float) $item['CapacityUnits'] : null,
177+
'ReadCapacityUnits' => isset($item['ReadCapacityUnits']) ? (float) $item['ReadCapacityUnits'] : null,
178+
'WriteCapacityUnits' => isset($item['WriteCapacityUnits']) ? (float) $item['WriteCapacityUnits'] : null,
179+
'Table' => empty($item['Table']) ? null : new Capacity([
180+
'ReadCapacityUnits' => isset($item['Table']['ReadCapacityUnits']) ? (float) $item['Table']['ReadCapacityUnits'] : null,
181+
'WriteCapacityUnits' => isset($item['Table']['WriteCapacityUnits']) ? (float) $item['Table']['WriteCapacityUnits'] : null,
182+
'CapacityUnits' => isset($item['Table']['CapacityUnits']) ? (float) $item['Table']['CapacityUnits'] : null,
183+
]),
184+
'LocalSecondaryIndexes' => empty($item['LocalSecondaryIndexes']) ? [] : $fn['map-SecondaryIndexesCapacityMap']($item['LocalSecondaryIndexes']),
185+
'GlobalSecondaryIndexes' => empty($item['GlobalSecondaryIndexes']) ? [] : $fn['map-SecondaryIndexesCapacityMap']($item['GlobalSecondaryIndexes']),
186+
]);
187+
}
188+
189+
return $items;
190+
};
191+
192+
/** @return array<string, \AsyncAws\DynamoDb\ValueObject\Capacity> */
193+
$fn['map-SecondaryIndexesCapacityMap'] = static function (array $json): array {
194+
$items = [];
195+
foreach ($json as $name => $value) {
196+
$items[(string) $name] = Capacity::create($value);
197+
}
198+
199+
return $items;
200+
};
201+
$this->Responses = empty($data['Responses']) ? [] : (function (array $json) use (&$fn): array {
202+
$items = [];
203+
foreach ($json as $name => $value) {
204+
$items[(string) $name] = $fn['list-ItemList']($value);
205+
}
206+
207+
return $items;
208+
})($data['Responses']);
209+
$this->UnprocessedKeys = empty($data['UnprocessedKeys']) ? [] : $fn['map-BatchGetRequestMap']($data['UnprocessedKeys']);
210+
$this->ConsumedCapacity = empty($data['ConsumedCapacity']) ? [] : $fn['list-ConsumedCapacityMultiple']($data['ConsumedCapacity']);
211+
}
212+
}

0 commit comments

Comments
 (0)