Completed
Push — master ( b2766c...abe4a2 )
by Sam
02:53
created

StatusManager::handleInstanceStatus()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 33
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 33
rs 8.439
cc 5
eloc 15
nc 16
nop 1
1
<?php
2
3
namespace Jalle19\StatusManager\Manager;
4
5
use Jalle19\StatusManager\Configuration\Instance;
6
use Jalle19\StatusManager\Event\ConnectionSeenEvent;
7
use Jalle19\StatusManager\Event\Events;
8
use Jalle19\StatusManager\Event\InputSeenEvent;
9
use Jalle19\StatusManager\Event\InstanceStatusCollectionRequestEvent;
10
use Jalle19\StatusManager\Event\InstanceSeenEvent;
11
use Jalle19\StatusManager\Event\InstanceStateEvent;
12
use Jalle19\StatusManager\Event\InstanceStatusUpdatesEvent;
13
use Jalle19\StatusManager\Event\SubscriptionSeenEvent;
14
use Jalle19\StatusManager\Event\SubscriptionStateChangeEvent;
15
use Jalle19\StatusManager\Instance\InstanceStatus;
16
use Jalle19\StatusManager\Instance\InstanceStatusCollection;
17
use Jalle19\StatusManager\Subscription\StateChangeParser;
18
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
19
20
/**
21
 * Class StatusManager
22
 * @package   Jalle19\StatusManager\Manager
23
 * @copyright Copyright &copy; Sam Stenvall 2015-
24
 * @license   https://www.gnu.org/licenses/gpl.html The GNU General Public License v2.0
25
 */
26
class StatusManager extends AbstractManager implements EventSubscriberInterface
27
{
28
29
	/**
30
	 * @inheritdoc
31
	 */
32
	public static function getSubscribedEvents()
33
	{
34
		return [
35
			Events::MAIN_LOOP_STARTING => 'onMainLoopStarted',
36
			Events::MAIN_LOOP_TICK     => 'onMainLoopTick',
37
		];
38
	}
39
40
41
	/**
42
	 * Called right before the main loop is started
43
	 */
44
	public function onMainLoopStarted()
45
	{
46
		// Log information about the database
47
		$this->logger->debug('Using database at {databasePath}', [
48
			'databasePath' => $this->configuration->getDatabasePath(),
49
		]);
50
51
		// Log information about the configured instances
52
		$instances = $this->configuration->getInstances();
53
54
		$this->logger->info('Managing {instances} instances:', [
55
			'instances' => count($instances),
56
		]);
57
58
		foreach ($instances as $configuredInstance)
59
		{
60
			$instance = $configuredInstance->getInstance();
61
62
			$this->logger->info('  {address}:{port}', [
63
				'address' => $instance->getHostname(),
64
				'port'    => $instance->getPort(),
65
			]);
66
67
			$this->eventDispatcher->dispatch(Events::INSTANCE_SEEN, new InstanceSeenEvent($instance));
68
		}
69
	}
70
71
72
	/**
73
	 * Called periodically by the event loop
74
	 */
75
	public function onMainLoopTick()
76
	{
77
		/* @var InstanceStatusCollectionRequestEvent $event */
78
		$event = $this->eventDispatcher->dispatch(Events::INSTANCE_STATUS_COLLECTION_REQUEST,
79
			new InstanceStatusCollectionRequestEvent());
80
81
		$statusCollection = $this->getStatusMessages($event->getInstanceStatusCollection());
82
83
		foreach ($statusCollection->getInstanceStatuses() as $instanceStatus)
84
			$this->handleInstanceStatus($instanceStatus);
85
86
		$this->eventDispatcher->dispatch(Events::INSTANCE_STATUS_UPDATES,
87
			new InstanceStatusUpdatesEvent($statusCollection));
88
	}
89
90
91
	/**
92
	 * @param InstanceStatus $instanceStatus
93
	 */
94
	private function handleInstanceStatus(InstanceStatus $instanceStatus)
95
	{
96
		$instanceName = $instanceStatus->getInstanceName();
97
98
		$this->logger->debug('Got status updates from {instanceName}', [
99
			'instanceName' => $instanceName,
100
		]);
101
102
		// Persist connections
103
		foreach ($instanceStatus->getConnections() as $connection)
104
		{
105
			$this->eventDispatcher->dispatch(Events::CONNECTION_SEEN,
106
				new ConnectionSeenEvent($instanceName, $connection));
107
		}
108
109
		// Persist inputs
110
		foreach ($instanceStatus->getInputs() as $input)
111
			$this->eventDispatcher->dispatch(Events::INPUT_SEEN, new InputSeenEvent($instanceName, $input));
112
113
		// Persist running subscriptions
114
		foreach ($instanceStatus->getSubscriptions() as $subscription)
115
		{
116
			$this->eventDispatcher->dispatch(Events::SUBSCRIPTION_SEEN,
117
				new SubscriptionSeenEvent($instanceName, $subscription));
118
		}
119
120
		// Handle subscription state changes
121
		foreach ($instanceStatus->getSubscriptionStateChanges() as $subscriptionStateChange)
122
		{
123
			$this->eventDispatcher->dispatch(Events::SUBSCRIPTION_STATE_CHANGE,
124
				new SubscriptionStateChangeEvent($instanceName, $subscriptionStateChange));
125
		}
126
	}
127
128
129
	/**
130
	 * Retrieves and returns all status messages for the configured
131
	 * instances
132
	 *
133
	 * @param \SplObjectStorage $instances the instances and their state
134
	 *
135
	 * @return InstanceStatusCollection
136
	 */
137
	private function getStatusMessages($instances)
138
	{
139
		$collection = new InstanceStatusCollection();
140
141
		foreach ($instances as $instance)
142
		{
143
			/* @var Instance $instance */
144
			$tvheadend     = $instance->getInstance();
145
			$instanceName  = $instance->getName();
146
			$instanceState = $instances[$instance];
147
148
			// Collect statuses from currently reachable instances
149
			if ($instanceState->isReachable())
150
			{
151
				try
152
				{
153
					$collection->add(new InstanceStatus(
154
						$instanceName,
155
						$tvheadend->getInputStatus(),
156
						$tvheadend->getSubscriptionStatus(),
157
						$tvheadend->getConnectionStatus(),
158
						StateChangeParser::parseStateChanges($tvheadend->getLogMessages())));
159
160
					$this->eventDispatcher->dispatch(Events::INSTANCE_STATE_REACHABLE,
161
						new InstanceStateEvent($instance));
162
				}
163
				catch (\Exception $e)
164
				{
165
					$this->eventDispatcher->dispatch(Events::INSTANCE_STATE_UNREACHABLE,
166
						new InstanceStateEvent($instance));
167
				}
168
			}
169
			else
170
			{
171
				$this->eventDispatcher->dispatch(Events::INSTANCE_STATE_MAYBE_REACHABLE,
172
					new InstanceStateEvent($instance));
173
			}
174
		}
175
176
		return $collection;
177
	}
178
179
}
180