The GET Collection and Item operations do not always return the latest data for document resources after updating a resource via the PATCH or PUT operations; sometimes the old data is returned.
Important: This happens only in the production environment docker compose -f compose.yaml -f compose.prod.yaml up --build. I don't know if this is related to the production setup.
How to reproduce
<?php
declare(strict_types=1);
namespace App\Document;
use ApiPlatform\Metadata\ApiResource;
use App\Repository\ProductRepository;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use Doctrine\ODM\MongoDB\Types\Type;
#[ApiResource]
#[ODM\Document(collection: 'products', repositoryClass: ProductRepository::class)]
class Product
{
#[ODM\Id(type: Type::INT, strategy: 'INCREMENT')]
private ?int $id = null;
#[ODM\Field(type: Type::STRING, nullable: true)]
private ?string $name = null;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(?string $name): static
{
$this->name = $name;
return $this;
}
}
Create a new Product via the POST API.
Update the Product data via the PATCH or PUT API.
Hit the GET Collection of Products or the GET Single Product APIs multiple times, and you'll see that sometimes the latest data is not returned.
I had to create custom state provider for the GET item operation and call the refresh method after retrieving the object from the built-in state provider.
Custom state provider:
<?php
declare(strict_types=1);
namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use App\Document\Product;
use App\Repository\ProductRepository;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
final readonly class ProductProvider implements ProviderInterface
{
public function __construct(
#[Autowire(service: 'api_platform.doctrine_mongodb.odm.state.item_provider')]
private ProviderInterface $itemProvider,
private ProductRepository $productRepository
) {
}
public function provide(Operation $operation, array $uriVariables = [], array $context = []): ?Product
{
/** @var Product|null $product */
$product = $this->itemProvider->provide($operation, $uriVariables, $context);
if (!$product) {
return null;
}
$this->productRepository->getDocumentManager()->refresh($product);
return $product;
}
}
Updated document:
<?php
declare(strict_types=1);
namespace App\Document;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Delete;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Patch;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\Put;
use App\Repository\ProductRepository;
use App\State\ProductProvider;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use Doctrine\ODM\MongoDB\Types\Type;
#[ApiResource(
operations: [
new GetCollection(),
new Post(),
new Get(provider: ProductProvider::class),
new Patch(),
new Put(),
new Delete(),
],
)]
#[ODM\Document(collection: 'products', repositoryClass: ProductRepository::class)]
class Product
{
#[ODM\Id(type: Type::INT, strategy: 'INCREMENT')]
private ?int $id = null;
#[ODM\Field(type: Type::STRING, nullable: true)]
private ?string $name = null;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(?string $name): static
{
$this->name = $name;
return $this;
}
}
I haven't found a solution for the Get Collection operation yet.
API Platform version(s) affected: 3.3.5
Description
The
GET
Collection and Item operations do not always return the latest data for document resources after updating a resource via thePATCH
orPUT
operations; sometimes the old data is returned.Important: This happens only in the production environment
docker compose -f compose.yaml -f compose.prod.yaml up --build
. I don't know if this is related to the production setup.How to reproduce
POST
API.PATCH
orPUT
API.GET
Collection of Products or theGET
Single Product APIs multiple times, and you'll see that sometimes the latest data is not returned.Use this repo for testing the above.
Possible Solution
I had to create custom state provider for the GET item operation and call the
refresh
method after retrieving the object from the built-in state provider.Custom state provider:
Updated document:
I haven't found a solution for the Get Collection operation yet.
Additional Context
Recording: https://www.awesomescreenshot.com/video/28637492?key=483e51522dd7bd03d915244bf090e6ff