Сущность в Symfony 4.3 генерирует ошибку 502 Bad Gateway

Тема в разделе "PHP", создана пользователем verfaa, 1 фев 2020.

XEvil 4.0 Релиз Состоялся!
Метки:
Модераторы: latteo
  1. verfaa

    verfaa

    Регистр.:
    29 янв 2007
    Сообщения:
    407
    Симпатии:
    47
    Разрабатываю локально небольшой проект на symfony. Использую докер. Сайт на symfony 4.3.11
    В процессе разработки внезапно на нескольких страницах сайта получил ошибку 502 Bad Gateway nginx/1.15.12
    [​IMG]

    Я выяснил, что эта ошибка появляется только на страницах, где через ParamConverter подгружается сущность Project

    Код:
    public function show(Project $project): Response

    Где-то в ней затесалась ошибка, вот только не могу понять где. Ранее эта сущность работала нормально. Никаких ошибок, ни при очистке кеша cache:clear, ни при генерации миграции не выводилось Project:
    Код:
        declare(strict_types=1);
      
        namespace App\Model\Work\Entity\Projects\Project;
      
        use App\Model\Work\Entity\Members\Member\Member;
        use App\Model\Work\Entity\Members\Member\Id as MemberId;
        use App\Model\Work\Entity\Projects\Project\Department\Department;
        use App\Model\Work\Entity\Projects\Project\Department\Id as DepartmentId;
        use App\Model\Work\Entity\Projects\Role\Role;
        use Doctrine\Common\Collections\ArrayCollection;
        use Doctrine\ORM\Mapping as ORM;
      
        /**
         * @ORM\Entity(repositoryClass="App\Model\Work\Entity\Projects\Project\ProjectRepository")
         * @ORM\Table(name="work_projects_projects")
         */
        class Project
        {
      
            /**
             * @ORM\Column(type="work_projects_project_id")
             * @ORM\Id
             * @var Id
             */
            private $id;
      
            /**
             * @var string
             * @ORM\Column(type="string")
             */
            private $name;
      
            /**
             * Порядок сортировки для отображения на сайте
             * @var int
             * @ORM\Column(type="integer")
             */
            private $sort;
      
            /**
             * @var Status
             * @ORM\Column(type="work_projects_project_status", length=16)
             */
            private $status;
      
            /**
             * @var ArrayCollection|Department[]
             * @ORM\OneToMany(
             *     targetEntity="App\Model\Work\Entity\Projects\Project\Department\Department", mappedBy="project",
             *     orphanRemoval=true, cascade={"all"}
             * )
             *
             * @ORM\OrderBy({"name" = "ASC"})
             */
            private $departments;
      
            /**
             * @var ArrayCollection|Membership[]
             * @ORM\OneToMany(targetEntity="Membership", mappedBy="project", orphanRemoval=true, cascade={"all"})
             */
            private $memberships;
      
            public function __construct(Id $id, string $name, int $sort)
            {
                $this->id = $id;
                $this->name = $name;
                $this->sort = $sort;
                $this->status = new Status(Status::ACTIVE);
                $this->departments = new ArrayCollection();
                $this->memberships = new ArrayCollection();
            }
      
            public function edit(string $name, int $sort): void
            {
                $this->name = $name;
                $this->sort = $sort;
            }
      
            public function reinstate(): void
            {
                if($this->status->isActive()){
                    throw new \DomainException("Project already active.");
                }
                $this->status = new Status(Status::ACTIVE);
            }
      
            public function archive(): void
            {
                if($this->status->isArchived()){
                    throw new \DomainException("Project already archived.");
                }
                $this->status = new Status(Status::ARCHIVED);
            }
      
            public function addDepartment(DepartmentId $id, string $department_name): void
            {
                foreach ($this->departments as $department){
                    if($department->isNameEqual($department_name)){
                        throw new \DomainException("Department already exists.");
                    }
                }
                $this->departments->add( new Department($this, $id, $department_name) );
            }
      
            public function editDepartment(DepartmentId $id, string $name): void
            {
                foreach ($this->departments as $department) {
                    if($department->getId()->isEqual($id)){
                        $department->edit($name);
                        return;
                    }
                }
                throw new \DomainException("Department is not found.");
            }
      
            public function removeDepartment(DepartmentId $id): void
            {
                foreach ($this->departments as $key => $department){
                    if($department->getId()->isEqual($id)){
                        foreach ($this->memberships as $membership) {
                            if($membership->isForDepartment($department)){
                                throw new \DomainException("Unable to remove department with members.");
                            }
                        }
                        $this->departments->remove($key);
                        return;
                    }
                }
                throw new \DomainException("Department is not found.");
            }
      
            /**
             * Имеется ли такой учасник в текущем проекте?
             * @param MemberId $id - ID учасника
             * @return bool
             */
            public function hasMember(MemberId $id): bool
            {
                foreach ($this->memberships as $membership) {
                    if($membership->isForMember($id)){
                        return true;
                    }
                }
                return false;
            }
      
            /**
             * @param Member         $member
             * @param DepartmentId[] $departmentIds
             * @param Role[]         $roles
             * @throws \Exception
             */
            public function addMember(Member $member, array $departmentIds, array $roles): void
            {
                foreach ($this->memberships as $membership) {
                    if($membership->isForMember($member->getId())){
                        throw new \DomainException("Member already exists.");
                    }
                }
                $departments = array_map([$this, 'getDepartment'], $departmentIds);
                $this->memberships->add( new Membership($this, $member, $departments, $roles) );
            }
      
            public function editMember(MemberId $member, array $departmentIds, array $roles): void
            {
                foreach ($this->memberships as $membership) {
                    if($membership->isForMember($member)){
                        $membership->changeDepartments( array_map([$this, 'getDepartment'], $departmentIds) );
                        $membership->changeRoles($roles);
                        return;
                    }
                }
                throw new \DomainException("Member is not found.");
            }
      
            public function removeMember(MemberId $member): void
            {
                foreach ($this->memberships as $membership) {
                    if($membership->isForMember($member)){
                        $this->memberships->removeElement($membership);
                        return;
                    }
                }
                throw new \DomainException("Member is not found.");
            }
      
            public function isActive(): bool
            {
                return $this->status->isActive();
            }
      
            public function isArchived(): bool
            {
                return $this->status->isArchived();
            }
      
            public function getId(): Id
            {
                return $this->id;
            }
      
            public function getName(): string
            {
                return $this->name;
            }
      
            public function getSort(): int
            {
                return $this->sort;
            }
      
            public function getStatus(): Status
            {
                return $this->status;
            }
      
            /**
             * Возвращает объект Department по переданному ID департамента
             * @param DepartmentId $id
             * @return Department
             */
            public function getDepartment(DepartmentId $id): Department
            {
                foreach ($this->departments as $department) {
                    if($department->getId()->isEqual($id)){
                        return $department;
                    }
                }
                throw new \DomainException("Department is not found.");
            }
      
            /**
             * Для того, чтобы выводить департаменты в шаблоне
             * @return array
             */
            public function getDepartments(): array
            {
                return $this->departments->toArray();
            }
      
            public function getMemberships(): array
            {
                return $this->memberships->toArray();
            }
        }
    
    И почему не выводится, стандартная отладочная панель Symfony?

    В логах докер контейнера nginx это:
    Код:
        192.168.99.1 - - [01/Feb/2020:19:03:59 +0000] "GET /work/projects/ee0fc92e-93f6-4f52-833f-91c0a4777aaf HTTP/1.1" 502 560 "http://192.168.99.100:8080/work/projects/ee0fc92e-93f6-4f52-833f-91c0a4777aaf/settings/departments" "Mozilla/5.0 (Windows NT 6.3; Win64; x64) A
        ppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36" "-"
        2020/02/01 19:03:59 [error] 6#6: *327 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 192.168.99.1, server: , request: "GET /work/projects/ee0fc92e-93f6-4f52-833f-91c0a4777aaf HTTP/1.1", upstream: "fastcgi://172.26
        .0.3:9000", host: "192.168.99.100:8080", referrer: "http://192.168.99.100:8080/work/projects/ee0fc92e-93f6-4f52-833f-91c0a4777aaf/settings/departments"
    
    Но я думаю, ошибка именно в сущности, т.к. остальные страницы сайта работают отлично.
     
  2. Sorcus

    Sorcus Sorcus. A New Beginning.

    Moderator
    Регистр.:
    10 июл 2011
    Сообщения:
    498
    Симпатии:
    878
    Тебе ошибки не Nginx-а нужны, а PHP.
     
  3. garphild

    garphild Постоялец

    Регистр.:
    19 май 2009
    Сообщения:
    56
    Симпатии:
    31
    502 означает что в контейнере докера, который отвечает за php есть проблема. Сам nginx/apache про эту проблему никогда ничего не скажет. Идите в контейнер с php-fpm (172.26.0.3) и смотрите конкретно логи php-fpm.

    Это означает, что контейнер отваливается. Более подробно - логи. Это точно не тайм-аут. Ошибка на стороне части скрипта обрабатывающей роут /work/projects/ee0fc92e-93f6-4f52-833f-91c0a4777aaf. По логам вот туда смотрите. Если не по логам, то найдите хендлер раута и прогуляйтесь по нему с отладчиком или банальным print_r(...). Лично у меня была похожая проблема в миддлвейре, который некорректно обрабатывал ID запрашиваемого ресурса, так как в базе DBA прописал нестандартный PRIMARY.