Skip to content
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

refacto: use Weakmap for UnitOfWork internal storage instead of uid i… #90

Merged
merged 1 commit into from
Dec 26, 2024

Conversation

vgreb
Copy link
Contributor

@vgreb vgreb commented Dec 17, 2024

Q A
Bug fix? yes/no
New feature? yes/no
BC breaks? yes/no
Deprecations? yes/no
Tests pass? yes
Licence Apache-2.0
Fixed tickets #1234

I proposed to add this feature in v3.10.0 and not wait the release of v4.0

@vgreb vgreb force-pushed the feature/use-weakmap branch 2 times, most recently from 7d40150 to 8a663ca Compare December 18, 2024 09:15
src/Ting/Repository/HydratorSingleObject.php Outdated Show resolved Hide resolved
@@ -58,6 +59,9 @@ public function __construct(
$this->connectionPool = $connectionPool;
$this->metadataRepository = $metadataRepository;
$this->queryFactory = $queryFactory;
$this->entities = new WeakMap();
$this->entitiesChanged = new WeakMap();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure about this change?

If we do that:

$entity = $ting->getById(12);
$entity->setSomething('foobaz');
$entity = null;

Or:

$entity = new MyEntity();
$ting->save($entity);
$entity = null;

Won't it be removed from the weakmap so the change wont be persisted?

Copy link
Contributor

@xavierleune xavierleune Dec 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the first case you're right, it's expected. As the app doesn't retain the entity, no need for ting to keep working with it.
For the second use case, no, as save processes the changes immediately.
But if you use the UnitOfWork, there is indeed a bug. Good catch !
Like this:

$myEntities = $ting->getBy(['awesome' => true]);

foreach ($myEntities as $entity) {
    $entity->setAwesome = false;
    $unitOfWork->pushSave($entity);
    // After this loop the entity will be destroyed by GC, because the refcount will drop to 0, except for the last one
}
$unitOfWork->process();

I think entities that have been sent to UnitOfWork should have a real reference, not a weak one.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fast reply @xavierleune

If my understanding is correct, it means we should preserve $entitiesShouldBePersisted as an array

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Ngob Indeed, I think that's correct

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Ngob @xavierleune I've switch back $entitiesShouldBePersisted to an array, however this may have a impact in performances.
Let me explain, UnitofWork::process() loops over the property $entitiesShouldBePersisted and forward the uuid to methods process*(). In order to retrieve the corresponding entity, I need to iterate on the WeakMap $entities.
I don't kwow about big of an impact this this for performance.

Any thoughts ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually you should keep the entity in $entitiesShouldBePersisted, if not we are back to the same issue. No tingUuid should exists anymore.
You can index $entitiesShouldBePersisted with spl_oject_hash if you need to have a unique identifier (note sure if needed). Sounds good ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something bugles me, why change $entitiesShouldBePersisted to an array ? It only stores the persistence state. However, the entity is actually stored in $entityChanged (cf methods processManaged, processNew, processDelete).
Am I wrong ?

@vgreb vgreb force-pushed the feature/use-weakmap branch from 04d3220 to 9715947 Compare December 21, 2024 16:43
@vgreb vgreb requested review from xavierleune and Ngob December 23, 2024 12:46
@vgreb vgreb force-pushed the feature/use-weakmap branch 3 times, most recently from c1b4122 to 30ba074 Compare December 23, 2024 14:42
@xavierleune
Copy link
Contributor

@vgreb follow up on this, here is a patch after a few tests on unitofwork:
unitofwork.PATCH

@vgreb vgreb force-pushed the feature/use-weakmap branch from 30ba074 to 47f72a8 Compare December 26, 2024 12:15
@vgreb
Copy link
Contributor Author

vgreb commented Dec 26, 2024

@xavierleune, I applied your patch. It's will avoid performance issues I mentionned earlier.

@vgreb vgreb merged commit dee53db into master Dec 26, 2024
5 checks passed
This was referenced Dec 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants