kodeine / laravel-meta

Fluent Meta Data for Eloquent Models, as if it is a property on your model
MIT License
398 stars 89 forks source link

Some metas are missing when the created events gets executed #102

Closed Temepest74 closed 1 year ago

Temepest74 commented 1 year ago

I have a notification hooked to a model created event. There, I need a meta value. The problem is, the values sometimes are pressent, sometimes not. From 5 values I should have had, I sometimes (not always) get ony 3-4. I know they exist because I have all 5 inside my db, with the same exact created_at value.

siamak2 commented 1 year ago

Laravel meta is using saving event to save metas to database. I believe that Laravel fires created event first then fires saved event. However this shouldn't be a problem in created event because even when metas not saved to database they're still attached to current instance of the model.

Are you handling the notification in a queue? if yes, Laravel only stores model id in the job then retrieve the model from database when job is running. if the job start running immediately, it's a possibility that saving event is not fired yet or Laravel meta is still saving them to database (one by one) and that's why you get partial or none of the metas.

Temepest74 commented 1 year ago

Yeah, this is exactly what I am doing. Do you have any solutions?

siamak2 commented 1 year ago

You can remove SerializesModels trait from the job. this way the model will be serialized with the all of the metas in job payload but this will increase your job payload. It is important not to save the model or any of the metas in this job. because the metas in the job have not been saved to database and don't have an id and in the mean time, main request is saving them to database. if you try to update the model in the job, metas will be saved again and you will get duplicate metas in you database or some other unexpected behavior.

Temepest74 commented 1 year ago

Hmm, it seems to work on my dev env. I will put it in prod and if still works, I will close this issue

Temepest74 commented 1 year ago

Still not working. I should mention that my workflow is: Comment Model fires created event which is connected with dispatchesEvents to my own CommentCreated event

    protected $dispatchesEvents = [
        'created' => CommentCreated::class,
    ];

where I removed the SerializesModels trait

class CommentCreated
{
    use Dispatchable, InteractsWithSockets;

    public Comment $comment;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct(
        Comment $comment
    ) {
        $this->comment= $comment;
    }
}

Now, I listen to this event like this inside EventServiceProvider

        CommentCreated::class => [
            NotifyOfCreatedComment::class,
        ],

Which will fire an notification

class NotifyOfCreatedComment
{
    public function handle(
        CommentCreated $event
    ): void {
       $event->comment->notify(new NotificationsCommentCreated($event->comment));
    }
}

The bug will ocur inside toMail function, where I try to get the user email.

siamak2 commented 1 year ago

103 should fix your problem.

Once the PR merged, update laravel meta and use createdWithMetas event instead of created event

    protected $dispatchesEvents = [
        'createdWithMetas' => CommentCreated::class,
    ];
siamak2 commented 1 year ago

PR merged. Update laravel-meta and try createdWithMetas event and let me know if it works.

Temepest74 commented 1 year ago

It looks like it for now at least. Thank you