Laravel ShouldQueue returns incorrect result on swoole server

182 Views Asked by At

Description

When calling a service defined as a facade in a Job implemented as ShouldQueue, an incorrect result is displayed.

  • Octane Version: 1.2.12
  • Laravel Version: 9.9.0
  • PHP Version: 8.1.6
  • Server & Version: Swoole 4.8.5

Steps To Reproduce:

CLI

Job::dispatch(Model::find(5));
Job::dispatch(Model::find(10));
Job::dispatch(Model::find(5));
Job::dispatch(Model::find(10));
Job::dispatch(Model::find(5));
Job::dispatch(Model::find(10));

Result

In job
  • 5
  • 10
  • 5
  • 10
  • 5
  • 10
In service (defined as a facade called from job)
  • 5
  • 10
  • 5
  • 5
  • 5
  • 5
namespace App\Observers;

class MessageObserver
{
    public function created(Message $message)
    {
        SendMessage::dispatch($message); // call 1, 2, 3, 4, 5, 6
    }
}
namespace App\Jobs;

use App\Models\Message;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Message as MessageFacade;

class SendMessage implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $message;

    public function __construct(Message $message)
    {
        $this->message = $message;
    }

    public function handle()
    {
        // logger($this->message->id); => 1, 2, 3, 4, 5, 6
        MessageFacade::model($this->message)->send();
    }
}
namespace App\Services\Message;

use App\Models\Message;
use App\Services\Message\Services\Text;
use Illuminate\Support\Manager;

class MessageManager extends Manager
{
    protected $message;

    public function getDefaultDriver()
    {
        return null;
    }

    protected function createTextDriver()
    {
        return new Text($this->message);
    }

    public function model(Message $message)
    {
        $this->message = $message;
        // logger($this->message->id); => 1, 2, 3, 4, 5, 6

        return $this->driver($this->message->service->value);
    }
}
namespace App\Services\Message\Services;

use App\Models\Message;

class Text
{
    protected $message;

    public function __construct(Message $message)
    {
        $this->message = $message;
    }

    public function send()
    {
        ...
        // logger($this->message->id); => 1, 1, 1, 1, 1, 1
        ...
    }
}
namespace App\Providers;

use App\Services\Message\MessageManager;
use Illuminate\Support\ServiceProvider;

class MessageServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->bind('message', function ($app) {
          return new MessageManager($app);
        });
    }

    public function boot()
    {
        //
    }
}
1

There are 1 best solutions below

0
On BEST ANSWER

Solved.

This is not a swoole problem.

Even if the bind method was used in the service provider, the facade behaved like a singleton.

<?php

namespace App\Support\Facades;

use Illuminate\Support\Facades\Facade;

class Message extends Facade
{
  protected static function getFacadeAccessor()
  { 
    self::clearResolvedInstance('message'); // will be solved.

    return 'message';
  } 
}