Completed
Push — master ( ad12aa...1c1eb2 )
by De Cramer
10s
created

AbstractApplication::init()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 6
cts 6
cp 1
rs 9.6666
c 0
b 0
f 0
cc 1
eloc 6
nc 1
nop 1
crap 1
1
<?php
2
3
4
namespace eXpansion\Framework\Core\Services\Application;
5
6
use eXpansion\Framework\Core\Services\Console;
7
use Maniaplanet\DedicatedServer\Connection;
8
use Propel\Runtime\Connection\Exception\ConnectionException;
9
use Propel\Runtime\Propel;
10
use Psr\Log\LoggerInterface;
11
use Symfony\Component\Console\Output\OutputInterface;
12
13
abstract class AbstractApplication implements RunInterface
14
{
15
    /** Base eXpansion callbacks. */
16
    const EVENT_BEFORE_INIT = "expansion.before_init";
17
    const EVENT_AFTER_INIT = "expansion.after_init";
18
    const EVENT_READY = "expansion.ready";
19
    const EVENT_STOP = "expansion.stop";
20
21
    const EXPANSION_VERSION = "dev";
22
23
    /** @var Connection */
24
    protected $connection;
25
26
    /** @var DispatcherInterface */
27
    protected $dispatcher;
28
29
    /** @var Console */
30
    protected $console;
31
32
    /** @var bool */
33
    protected $isRunning = true;
34
    /**
35
     * @var LoggerInterface
36
     */
37
    private $logger;
38
39
    /**
40
     * Application constructor.
41
     *
42
     * @param DispatcherInterface $dispatcher
43
     * @param Connection $connection
44
     * @param Console $output
45
     * @param LoggerInterface $logger
46
     */
47 138
    public function __construct(
48
        DispatcherInterface $dispatcher,
49
        Connection $connection,
50
        Console $output,
51
        LoggerInterface $logger
52
    ) {
53 138
        $this->connection = $connection;
54 138
        $this->dispatcher = $dispatcher;
55 138
        $this->console = $output;
56 138
        $this->logger = $logger;
57 138
    }
58
59
    /**
60
     * Initialize eXpansion.
61
     *
62
     * @param OutputInterface $console
63
     *
64
     * @return $this
65
     */
66 1
    public function init(OutputInterface $console)
67
    {
68 1
        $this->console->init($console, $this->dispatcher);
69 1
        $this->dispatcher->dispatch(self::EVENT_BEFORE_INIT, []);
70 1
        $this->dispatcher->init($this->connection);
71 1
        $this->dispatcher->dispatch(self::EVENT_AFTER_INIT, []);
72
73 1
        return $this;
74
    }
75
76
    /**
77
     * Run eXpansion
78
     *
79
     * @inheritdoc
80
     */
81 2
    public function run()
82
    {
83
        // Time each cycle needs to take in microseconds. Wrunning 60 cycles per seconds to have optimal response time.
84 2
        $cycleTime = (1 / 60) * 1000000;
85
86
        // Running GC collect every 5 minutes should be sufficient.;
87 2
        $gcCycleTime = 60 * 5;
88
89
        // Time when we will force gc cycles.
90 2
        $maxGcCycleTime = 60 * 20;
91
92
        // Last time garbage collector ran. Assume that at start it ran.
93 2
        $lastGcTime = time();
94
95 2
        $this->console->writeln("Running preflight checks...");
96 2
        $this->connection->enableCallbacks(true);
97
98
        // need to send this for scripts to start callback handling
99
        try {
100 2
            $this->connection->triggerModeScriptEvent("XmlRpc.EnableCallbacks", ["True"]);
101
        } catch (\Exception $exception) {
102
            $this->connection->saveMatchSettings('MatchSettings/eXpansion-mode-fail-' . date(DATE_ISO8601) . '.txt');
103
            throw $exception;
104
        }
105
106 2
        $this->console->writeln("preflight checks OK.");
107
108 2
        $this->dispatcher->dispatch(self::EVENT_READY, []);
109
110 2
        $this->console->writeln("And takeoff");
111
112
        do {
113 2
            $startTime = microtime(true);
114
115
            // Run the actuall application
116 2
            $this->executeRun();
117
118 2
            $endTime = microtime(true);
119 2
            $delay = $cycleTime - (($endTime - $startTime) * 1000000);
120
121
            // If we got lot's of time and it's been a while since last GC collect let's run a garbage collector
122
            // cycle this iteration.
123 2
            if ($delay > $cycleTime / 2 && $lastGcTime < (time() - $gcCycleTime)) {
124
                // PHP does this automatically as well but in some mysterious ways it can sometimes keep in memory
125
                // hundred of mb's before running it.
126
                gc_collect_cycles();
127
                $lastGcTime = time();
128
129
                // Renew delay so that this iteration isn't much slower then the others
130
                $endTime = microtime(true);
131
                $delay = $cycleTime - (($endTime - $startTime) * 1000000);
132
            }
133
134 2
            if ($lastGcTime < (time() - $maxGcCycleTime)) {
135
                //It's been a while since last Garbage collection forcing it to go even through the application is
136
                // running slow.
137
                gc_collect_cycles();
138
                $lastGcTime = time();
139
140 2
            } elseif ($delay > 0) {
141 2
                usleep($delay);
142
            }
143 2
        } while ($this->isRunning);
144 2
    }
145
146
    /**
147
     * Stop eXpansion.
148
     */
149 2
    public function stopApplication()
150
    {
151 2
        $this->dispatcher->dispatch(self::EVENT_STOP, []);
152 2
        $this->isRunning = false;
153 2
    }
154
155
    abstract protected function executeRun();
156
}
157