0

I know many people asked this type of question but I believe mine is different because I only encouter the error when trying to run the message async.

This is just a project for personal use to try to implement the strava premium functions my self (I made it work but I just want to handle everything better). Im new to symfony and so I hope I made the question and the problem clear for someone to give me some tips.

In my controller I make a call to function to start loading activities from the strava api and then making some calculations to persist the the new activities and flush them. I encounter this error when running the message: Handling "App\Message\StartLoadingMessage" failed: A new entity was found through the relationship 'App\Entity\Activities#user' that was not configured to cascade persist operations for entity: App\Entity\User@42792

I only encounter this error when running the message async.If im running it synchronously it works perfectly fine. I want to be able to run it async as that makes the user experience just way better if I can do other things while the function is running in the background.

In my controller I make the call to start loading like so:

$user = $this->getUser();
$messageBus->dispatch(new StartLoadingMessage($user));

The StartLoadingMessage class is just the standard message class

The StartLoadingMessageHandler class is like so:

class StartLoadingMessageHandler implements MessageHandlerInterface
{
    public function __construct(private StravaRequests $startLoading)
    {
        $this->startLoading = $startLoading;
    }

    public function __invoke(StartLoadingMessage $message)
    {
        // Run the background task here
        $user = $message->getUser();
        $this->startLoading->startLoading($user);
    }
}

And then in the actual startloading function I make some api calls (without errors) and some calculations and then I try to add the newly created activities to the database like this:

            $newActivity = new Activity();
            $newActivity->setUser($user);
           
            $newActivity->setStravaId($activity['id']);
            $newActivity->setType($activity['type']);
            $newActivity->setRecordData($peaks);
            $this->em->persist($newActivity);
            $this->em->flush();

EDIT after this im also updating the user as so:

 if (count($activities) > 0) {
            $latestEpochBeforeDate = 
          strtotime($activities[count($activities) - 1]['start_date']);
            $user->setLatestLoadedEpochDate($latestEpochBeforeDate);
            
            $this->em->flush();
        }

I dont know if this is the right way im you need to create one new Entity (Activity in my case) and update an other (User)

In the Activity entity I made sure to add the cascade persist line:

 #[ORM\ManyToOne(inversedBy: 'activities', cascade:['persist'])]
    #[ORM\JoinColumn(nullable: false)]
    private ?User $user = null;

And I tried to explicitly call EntityManager#persist() on the user entity in my startloading function but that does not work either.

1 Answer 1

1

I guess the problem comes from your User entity that is currently detached from Doctrine scope when running in async. The way to correct it is to use below code if your version of Doctrine accept it:

$newActivity = new Activity();
$newActivity->setUser($user);
           
$newActivity->setStravaId($activity['id']);
$newActivity->setType($activity['type']);
$newActivity->setRecordData($peaks);

$this->em->merge($user);
$this->em->persist($newActivity);
$this->em->flush();

Or simply query the User using your UserRepository with the User ID you have and replace your actual $user variable.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for the response. I tried querying the User using the UserRepository. The original error is gone but it is replaced with a Integrity constraint violation: 1062 Duplicate entry '[email protected]' for key 'user.UNIQ_......' This is still only happening when im running it async. Its so weird to me why its only happening when running async. Idk if it matters but im making it run async by adding: App\Message\StartLoadingMessage: async in the messenger.yaml file. Also made an edit to the post which could be important
@hidde Could you please share with us a dump of your User? And also could you confirm that in you Activity entity when you do ->setUser(), you have correctly set a $user->addActivity($this) in?
I did not set $user->addActivity($this) in the Acitvity entity. That made it work!! Thank you. Is that something you need to do manually everytime, because $user->getActivities() would give me all the activities related to that user when the startloading function worked sync. You have already answered my question so just asking out of curiosity.
You are not forced to do it everytime. Just do it in Activity->setUser() and/or User->addActivity() like describe here: symfonycasts.com/screencast/symfony4-doctrine-relations/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.