Skip to content

Add logical cursor for long query parameters #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
5adecfa
Add logical cursor for long query parameters
JoMessina Dec 7, 2023
d32cc33
fix type phpstan, manage api return's cursor with the array of parame…
JoMessina Dec 8, 2023
1cdb190
remove IGNORE_ENV_TRUE parameter for cs-fixer
JoMessina Dec 8, 2023
c03dc1d
Ignore a rule from phpstan
JoMessina Jan 9, 2024
3c8721e
fix from cs fixer
JoMessina Jan 9, 2024
9748ff3
Merge branch 'main' into feature/add-cursor-for-long-filter
JoMessina Jan 9, 2024
b0ca2a1
fix from cs fixer
JoMessina Jan 9, 2024
3a5066c
change phpstan config for level 5
JoMessina Jan 9, 2024
1442b14
Change a method name
JoMessina Jan 9, 2024
e973d99
Refactored the way filters are handled
gplanchat Jan 18, 2024
730e90b
[rector] Rector fixes
actions-user Jan 18, 2024
c0a80ee
refacto extractors, add withGroups and withFilters methods
JoMessina Jan 19, 2024
afc78d5
manage page count, fix extractor to use api pagination
JoMessina Jan 23, 2024
047ae6e
fix and add tests for extractors
JoMessina Jan 24, 2024
8854a9c
Merge branch 'main' into feature/add-cursor-for-long-filter
JoMessina Jan 24, 2024
7930389
[rector] Rector fixes
actions-user Jan 24, 2024
d9edd24
Refactored the way filters are handled
gplanchat Jan 30, 2024
784d8a4
[rector] Rector fixes
actions-user Jan 30, 2024
51dbb92
Fixed errors in the unit tests
gplanchat Jan 30, 2024
0ce5f65
Changed the variadic methods to use array_push instead of foreach
gplanchat Jan 30, 2024
912c39c
remove a cast on string, add a catch for UndefinedOptionsException
JoMessina Feb 2, 2024
8f501aa
[rector] Rector fixes
actions-user Feb 2, 2024
dca47a4
Fix client api version to 2.4
JoMessina Jan 31, 2024
9083255
update api-client-magento to lock symfony/serializer
JoMessina Feb 9, 2024
edfe529
valid phpstan 7, use rector and cs-fixer
JoMessina Feb 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 0 additions & 23 deletions .github/workflows/phpstan-7.yaml

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: PHPStan level 6
name: PHPStan level 8
on: push
jobs:
phpstan-6:
phpstan-9:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
Expand All @@ -20,4 +20,4 @@ jobs:
uses: php-actions/phpstan@v3
with:
path: src/
level: 6
level: 9
6 changes: 3 additions & 3 deletions .github/workflows/quality.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Quality (PHPStan lvl 5)
name: Quality (PHPStan lvl 7)
on: push
jobs:
cs-fixer:
Expand All @@ -12,7 +12,7 @@ jobs:
run: |
wget -q https://cs.symfony.com/download/php-cs-fixer-v3.phar -O php-cs-fixer
chmod a+x php-cs-fixer
PHP_CS_FIXER_IGNORE_ENV=true ./php-cs-fixer fix src --dry-run
./php-cs-fixer fix src --dry-run

phpstan:
runs-on: ubuntu-latest
Expand All @@ -32,4 +32,4 @@ jobs:
uses: php-actions/phpstan@v3
with:
path: src/
level: 5
level: 7
18 changes: 11 additions & 7 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
parameters:
level: 7
treatPhpDocTypesAsCertain: false
150 changes: 127 additions & 23 deletions src/CategoryLookup.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,55 +7,159 @@
use Kiboko\Component\Bucket\AcceptanceResultBucket;
use Kiboko\Component\Bucket\EmptyResultBucket;
use Kiboko\Component\Bucket\RejectionResultBucket;
use Kiboko\Contract\Bucket\RejectionResultBucketInterface;
use Kiboko\Contract\Mapping\CompiledMapperInterface;
use Kiboko\Contract\Pipeline\TransformerInterface;
use Psr\SimpleCache\CacheInterface;
use Kiboko\Magento\Client;
use Kiboko\Magento\Exception\GetV1CategoriesCategoryIdBadRequestException;
use Kiboko\Magento\Exception\UnexpectedStatusCodeException;
use Kiboko\Magento\Model\CatalogDataCategoryInterface;
use Kiboko\Magento\Model\ErrorResponse;
use Psr\Http\Client\NetworkExceptionInterface;
use Psr\Log\LoggerInterface;

/**
* @template InputType of array
* @template OutputType of InputType|array
*
* @implements TransformerInterface<InputType, OutputType>
*/
final readonly class CategoryLookup implements TransformerInterface
{
/**
* @param CompiledMapperInterface<CatalogDataCategoryInterface, InputType, OutputType> $mapper
*/
public function __construct(
private \Psr\Log\LoggerInterface $logger,
private \Kiboko\Magento\Client $client,
private CacheInterface $cache,
private string $cacheKey,
private LoggerInterface $logger,
private Client $client,
private CompiledMapperInterface $mapper,
private string $mappingField,
) {
}

/**
* @return RejectionResultBucketInterface<OutputType>
*/
private function rejectErrorResponse(ErrorResponse $response): RejectionResultBucketInterface
{
$this->logger->error(
$response->getMessage(),
[
'resource' => 'getV1CategoriesCategoryId',
'method' => 'get',
],
);

return new RejectionResultBucket($response->getMessage(), null);
}

/**
* @return RejectionResultBucketInterface<OutputType>
*/
private function rejectInvalidResponse(): RejectionResultBucketInterface
{
$this->logger->error(
$message = 'The result provided by the API client does not match the expected type. The connector compilation may have fetched incompatible versions.',
[
'resource' => 'getV1CategoriesCategoryId',
'method' => 'get',
],
);

return new RejectionResultBucket($message, null);
}

/**
* @param InputType $line
*
* @return OutputType
*/
public function passThrough(array $line): array
{
/* @var OutputType $line */
return $line;
}

public function transform(): \Generator
{
$line = yield new EmptyResultBucket();
while (true) {
if (null === $line) {
$line = yield new EmptyResultBucket();
continue;
}

if (null === $line[$this->mappingField]) {
$line = yield new AcceptanceResultBucket($line);
$line = yield new AcceptanceResultBucket($this->passThrough($line));
continue;
}

try {
$lookup = $this->cache->get(sprintf($this->cacheKey, $line[$this->mappingField]));

if (null === $lookup) {
$lookup = $this->client->getV1CategoriesCategoryId(
categoryId: (int) $line[$this->mappingField],
);
$lookup = $this->client->getV1CategoriesCategoryId(
categoryId: (int) $line[$this->mappingField],
);

if (!$lookup instanceof \Kiboko\Magento\Model\CatalogDataCategoryInterface) {
return;
}
if ($lookup instanceof ErrorResponse) {
$line = yield $this->rejectErrorResponse($lookup);
continue;
}

$this->cache->set(
sprintf($this->cacheKey, $line[$this->mappingField]),
$lookup,
);
if (!$lookup instanceof CatalogDataCategoryInterface) {
$line = yield $this->rejectInvalidResponse();
continue;
}
} catch (\RuntimeException $exception) {
$this->logger->warning($exception->getMessage(), ['exception' => $exception, 'item' => $line]);
} catch (NetworkExceptionInterface $exception) {
$this->logger->critical(
$exception->getMessage(),
[
'exception' => $exception,
'resource' => 'getV1CategoriesCategoryId',
'method' => 'get',
'categoryId' => (int) $line[$this->mappingField],
'mappingField' => $this->mappingField,
],
);
$line = yield new RejectionResultBucket(
'There are some network difficulties. We could not properly connect to the Magento API. There is nothing we could no to fix this currently. Please contact the Magento administrator.',
$exception,
$this->passThrough($line),
);
continue;
} catch (GetV1CategoriesCategoryIdBadRequestException $exception) {
$this->logger->error(
$exception->getMessage(),
[
'exception' => $exception,
'resource' => 'getV1CategoriesCategoryId',
'method' => 'get',
'categoryId' => (int) $line[$this->mappingField],
'mappingField' => $this->mappingField,
],
);
$line = yield new RejectionResultBucket(
sprintf('Something went wrong in the attempt to recover the category with id %d', (int) $line[$this->mappingField]),
'The source API rejected our request. Ignoring line. Maybe you are requesting on incompatible versions.',
$exception,
$line
$this->passThrough($line),
);
continue;
} catch (UnexpectedStatusCodeException $exception) {
$this->logger->critical(
$exception->getMessage(),
[
'exception' => $exception,
'resource' => 'getV1CategoriesCategoryId',
'method' => 'get',
'categoryId' => (int) $line[$this->mappingField],
'mappingField' => $this->mappingField,
],
);
$line = yield new RejectionResultBucket(
'The source API responded with a status we did not expect. Aborting. Please check the availability of the source API and if there are no rate limiting or redirections active.',
$exception,
$this->passThrough($line),
);

return;
}

$output = ($this->mapper)($lookup, $line);
Expand Down
Loading