Passed
Pull Request — master (#464)
by Kirill
04:42
created

JobsBootloader::boot()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 7
c 1
b 0
f 0
nc 2
nop 3
dl 0
loc 14
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Spiral\Jobs;
6
7
use Spiral\Boot\Bootloader\Bootloader;
8
use Spiral\Boot\KernelInterface;
9
use Spiral\Bootloader\ServerBootloader;
10
use Spiral\Core\Container;
11
use Spiral\Goridge\RPC\RPCInterface;
12
use Spiral\Jobs\Queue\Decorator;
13
use Spiral\Jobs\QueueInterface as QueueBridgeInterface;
14
use Spiral\RoadRunner\Jobs\Consumer;
15
use Spiral\RoadRunner\Jobs\ConsumerInterface;
16
use Spiral\RoadRunner\Jobs\Jobs;
17
use Spiral\RoadRunner\Jobs\JobsInterface;
18
use Spiral\RoadRunner\Jobs\Queue;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Spiral\Jobs\Queue. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
19
use Spiral\RoadRunner\Jobs\QueueInterface;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Spiral\Jobs\QueueInterface. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
20
use Spiral\RoadRunner\Jobs\Serializer\DefaultSerializer;
21
use Spiral\RoadRunner\Jobs\Serializer\SerializerInterface;
22
use Spiral\RoadRunner\WorkerInterface;
23
24
final class JobsBootloader extends Bootloader
25
{
26
    /**
27
     * @var array<class-string>
28
     */
29
    protected const DEPENDENCIES = [
30
        ServerBootloader::class,
31
    ];
32
33
    /**
34
     * @param Container $container
35
     * @param KernelInterface $kernel
36
     * @param JobDispatcher $jobs
37
     * @return void
38
     */
39
    public function boot(Container $container, KernelInterface $kernel, JobDispatcher $jobs): void
40
    {
41
        $kernel->addDispatcher($jobs);
42
43
        if (!$container->has(SerializerInterface::class)) {
44
            $this->registerJobsSerializer($container);
45
        }
46
47
        $this->registerJobs($container);
48
        $this->registerConsumer($container);
49
        $this->registerQueue($container);
50
51
        // Compatibility Bridges
52
        $this->registerQueueBridge($container);
53
    }
54
55
    /**
56
     * @param Container $container
57
     * @return void
58
     */
59
    private function registerQueueBridge(Container $container): void
60
    {
61
        $container->bindSingleton(
62
            Decorator::class,
63
            static function (JobsInterface $jobs, QueueInterface $queue): Decorator {
64
                return new Decorator($jobs, $queue);
65
            }
66
        );
67
68
        $container->bindSingleton(
69
            QueueBridgeInterface::class,
70
            static function (Decorator $decorator): QueueBridgeInterface {
71
                return $decorator;
72
            }
73
        );
74
    }
75
76
    /**
77
     * @param Container $container
78
     * @return void
79
     */
80
    private function registerJobsSerializer(Container $container): void
81
    {
82
        $container->bindSingleton(SerializerInterface::class, static function () {
83
            return new DefaultSerializer();
84
        });
85
    }
86
87
    /**
88
     * @param Container $container
89
     * @return void
90
     */
91
    private function registerConsumer(Container $container): void
92
    {
93
        $container->bindSingleton(
94
            Consumer::class,
95
            static function (WorkerInterface $worker, SerializerInterface $serializer): Consumer {
96
                return new Consumer($worker, $serializer);
97
            }
98
        );
99
100
        $container->bindSingleton(
101
            ConsumerInterface::class,
102
            static function (Consumer $consumer): ConsumerInterface {
103
                return $consumer;
104
            }
105
        );
106
    }
107
108
    /**
109
     * @param Container $container
110
     * @return void
111
     */
112
    private function registerJobs(Container $container): void
113
    {
114
        $container->bindSingleton(
115
            Jobs::class,
116
            static function (RPCInterface $rpc, SerializerInterface $serializer): Jobs {
117
                return new Jobs($rpc, $serializer);
118
            }
119
        );
120
121
122
        $container->bindSingleton(
123
            JobsInterface::class,
124
            static function (Jobs $jobs): JobsInterface {
125
                return $jobs;
126
            }
127
        );
128
    }
129
130
    /**
131
     * @param Container $container
132
     * @return void
133
     */
134
    private function registerQueue(Container $container): void
135
    {
136
        $container->bindSingleton(Queue::class, static function (JobsInterface $jobs): Queue {
137
            foreach ($jobs as $queue) {
138
                return $queue;
139
            }
140
141
            throw new \OutOfBoundsException('No available queues were registered');
142
        });
143
144
        $container->bindSingleton(QueueInterface::class, static function (Queue $queue): QueueInterface {
145
            return $queue;
146
        });
147
    }
148
}
149