@@ -37,118 +37,118 @@ |
||
| 37 | 37 | use Psr\Log\LoggerInterface; |
| 38 | 38 | |
| 39 | 39 | class InitialStateService implements IInitialStateService { |
| 40 | - /** @var LoggerInterface */ |
|
| 41 | - private $logger; |
|
| 42 | - |
|
| 43 | - /** @var string[][] */ |
|
| 44 | - private $states = []; |
|
| 45 | - |
|
| 46 | - /** @var Closure[][] */ |
|
| 47 | - private $lazyStates = []; |
|
| 48 | - |
|
| 49 | - /** @var Coordinator */ |
|
| 50 | - private $bootstrapCoordinator; |
|
| 51 | - |
|
| 52 | - /** @var IServerContainer */ |
|
| 53 | - private $container; |
|
| 54 | - |
|
| 55 | - public function __construct(LoggerInterface $logger, Coordinator $bootstrapCoordinator, IServerContainer $container) { |
|
| 56 | - $this->logger = $logger; |
|
| 57 | - $this->bootstrapCoordinator = $bootstrapCoordinator; |
|
| 58 | - $this->container = $container; |
|
| 59 | - } |
|
| 60 | - |
|
| 61 | - public function provideInitialState(string $appName, string $key, $data): void { |
|
| 62 | - // Scalars and JsonSerializable are fine |
|
| 63 | - if (is_scalar($data) || $data instanceof \JsonSerializable || is_array($data)) { |
|
| 64 | - if (!isset($this->states[$appName])) { |
|
| 65 | - $this->states[$appName] = []; |
|
| 66 | - } |
|
| 67 | - try { |
|
| 68 | - $this->states[$appName][$key] = json_encode($data, JSON_THROW_ON_ERROR); |
|
| 69 | - } catch (\JsonException $e) { |
|
| 70 | - $this->logger->error('Invalid '. $key . ' data provided to provideInitialState by ' . $appName, ['exception' => $e]); |
|
| 71 | - } |
|
| 72 | - return; |
|
| 73 | - } |
|
| 74 | - |
|
| 75 | - $this->logger->warning('Invalid '. $key . ' data provided to provideInitialState by ' . $appName); |
|
| 76 | - } |
|
| 77 | - |
|
| 78 | - public function provideLazyInitialState(string $appName, string $key, Closure $closure): void { |
|
| 79 | - if (!isset($this->lazyStates[$appName])) { |
|
| 80 | - $this->lazyStates[$appName] = []; |
|
| 81 | - } |
|
| 82 | - $this->lazyStates[$appName][$key] = $closure; |
|
| 83 | - } |
|
| 84 | - |
|
| 85 | - /** |
|
| 86 | - * Invoke all callbacks to populate the `states` property |
|
| 87 | - */ |
|
| 88 | - private function invokeLazyStateCallbacks(): void { |
|
| 89 | - foreach ($this->lazyStates as $app => $lazyStates) { |
|
| 90 | - foreach ($lazyStates as $key => $lazyState) { |
|
| 91 | - $startTime = microtime(true); |
|
| 92 | - $this->provideInitialState($app, $key, $lazyState()); |
|
| 93 | - $endTime = microtime(true); |
|
| 94 | - $duration = $endTime - $startTime; |
|
| 95 | - if ($duration > 1) { |
|
| 96 | - $this->logger->warning('Lazy initial state provider for {key} took {duration} seconds.', [ |
|
| 97 | - 'app' => $app, |
|
| 98 | - 'key' => $key, |
|
| 99 | - 'duration' => round($duration, 2), |
|
| 100 | - ]); |
|
| 101 | - } |
|
| 102 | - } |
|
| 103 | - } |
|
| 104 | - $this->lazyStates = []; |
|
| 105 | - } |
|
| 106 | - |
|
| 107 | - /** |
|
| 108 | - * Load the lazy states via the IBootstrap mechanism |
|
| 109 | - */ |
|
| 110 | - private function loadLazyStates(): void { |
|
| 111 | - $context = $this->bootstrapCoordinator->getRegistrationContext(); |
|
| 112 | - |
|
| 113 | - if ($context === null) { |
|
| 114 | - // To early, nothing to do yet |
|
| 115 | - return; |
|
| 116 | - } |
|
| 117 | - |
|
| 118 | - $initialStates = $context->getInitialStates(); |
|
| 119 | - foreach ($initialStates as $initialState) { |
|
| 120 | - try { |
|
| 121 | - $provider = $this->container->query($initialState->getService()); |
|
| 122 | - } catch (QueryException $e) { |
|
| 123 | - // Log an continue. We can be fault tolerant here. |
|
| 124 | - $this->logger->error('Could not load initial state provider dynamically: ' . $e->getMessage(), [ |
|
| 125 | - 'exception' => $e, |
|
| 126 | - 'app' => $initialState->getAppId(), |
|
| 127 | - ]); |
|
| 128 | - continue; |
|
| 129 | - } |
|
| 130 | - |
|
| 131 | - if (!($provider instanceof InitialStateProvider)) { |
|
| 132 | - // Log an continue. We can be fault tolerant here. |
|
| 133 | - $this->logger->error('Initial state provider is not an InitialStateProvider instance: ' . $initialState->getService(), [ |
|
| 134 | - 'app' => $initialState->getAppId(), |
|
| 135 | - ]); |
|
| 136 | - } |
|
| 137 | - |
|
| 138 | - $this->provideInitialState($initialState->getAppId(), $provider->getKey(), $provider); |
|
| 139 | - } |
|
| 140 | - } |
|
| 141 | - |
|
| 142 | - public function getInitialStates(): array { |
|
| 143 | - $this->invokeLazyStateCallbacks(); |
|
| 144 | - $this->loadLazyStates(); |
|
| 145 | - |
|
| 146 | - $appStates = []; |
|
| 147 | - foreach ($this->states as $app => $states) { |
|
| 148 | - foreach ($states as $key => $value) { |
|
| 149 | - $appStates["$app-$key"] = $value; |
|
| 150 | - } |
|
| 151 | - } |
|
| 152 | - return $appStates; |
|
| 153 | - } |
|
| 40 | + /** @var LoggerInterface */ |
|
| 41 | + private $logger; |
|
| 42 | + |
|
| 43 | + /** @var string[][] */ |
|
| 44 | + private $states = []; |
|
| 45 | + |
|
| 46 | + /** @var Closure[][] */ |
|
| 47 | + private $lazyStates = []; |
|
| 48 | + |
|
| 49 | + /** @var Coordinator */ |
|
| 50 | + private $bootstrapCoordinator; |
|
| 51 | + |
|
| 52 | + /** @var IServerContainer */ |
|
| 53 | + private $container; |
|
| 54 | + |
|
| 55 | + public function __construct(LoggerInterface $logger, Coordinator $bootstrapCoordinator, IServerContainer $container) { |
|
| 56 | + $this->logger = $logger; |
|
| 57 | + $this->bootstrapCoordinator = $bootstrapCoordinator; |
|
| 58 | + $this->container = $container; |
|
| 59 | + } |
|
| 60 | + |
|
| 61 | + public function provideInitialState(string $appName, string $key, $data): void { |
|
| 62 | + // Scalars and JsonSerializable are fine |
|
| 63 | + if (is_scalar($data) || $data instanceof \JsonSerializable || is_array($data)) { |
|
| 64 | + if (!isset($this->states[$appName])) { |
|
| 65 | + $this->states[$appName] = []; |
|
| 66 | + } |
|
| 67 | + try { |
|
| 68 | + $this->states[$appName][$key] = json_encode($data, JSON_THROW_ON_ERROR); |
|
| 69 | + } catch (\JsonException $e) { |
|
| 70 | + $this->logger->error('Invalid '. $key . ' data provided to provideInitialState by ' . $appName, ['exception' => $e]); |
|
| 71 | + } |
|
| 72 | + return; |
|
| 73 | + } |
|
| 74 | + |
|
| 75 | + $this->logger->warning('Invalid '. $key . ' data provided to provideInitialState by ' . $appName); |
|
| 76 | + } |
|
| 77 | + |
|
| 78 | + public function provideLazyInitialState(string $appName, string $key, Closure $closure): void { |
|
| 79 | + if (!isset($this->lazyStates[$appName])) { |
|
| 80 | + $this->lazyStates[$appName] = []; |
|
| 81 | + } |
|
| 82 | + $this->lazyStates[$appName][$key] = $closure; |
|
| 83 | + } |
|
| 84 | + |
|
| 85 | + /** |
|
| 86 | + * Invoke all callbacks to populate the `states` property |
|
| 87 | + */ |
|
| 88 | + private function invokeLazyStateCallbacks(): void { |
|
| 89 | + foreach ($this->lazyStates as $app => $lazyStates) { |
|
| 90 | + foreach ($lazyStates as $key => $lazyState) { |
|
| 91 | + $startTime = microtime(true); |
|
| 92 | + $this->provideInitialState($app, $key, $lazyState()); |
|
| 93 | + $endTime = microtime(true); |
|
| 94 | + $duration = $endTime - $startTime; |
|
| 95 | + if ($duration > 1) { |
|
| 96 | + $this->logger->warning('Lazy initial state provider for {key} took {duration} seconds.', [ |
|
| 97 | + 'app' => $app, |
|
| 98 | + 'key' => $key, |
|
| 99 | + 'duration' => round($duration, 2), |
|
| 100 | + ]); |
|
| 101 | + } |
|
| 102 | + } |
|
| 103 | + } |
|
| 104 | + $this->lazyStates = []; |
|
| 105 | + } |
|
| 106 | + |
|
| 107 | + /** |
|
| 108 | + * Load the lazy states via the IBootstrap mechanism |
|
| 109 | + */ |
|
| 110 | + private function loadLazyStates(): void { |
|
| 111 | + $context = $this->bootstrapCoordinator->getRegistrationContext(); |
|
| 112 | + |
|
| 113 | + if ($context === null) { |
|
| 114 | + // To early, nothing to do yet |
|
| 115 | + return; |
|
| 116 | + } |
|
| 117 | + |
|
| 118 | + $initialStates = $context->getInitialStates(); |
|
| 119 | + foreach ($initialStates as $initialState) { |
|
| 120 | + try { |
|
| 121 | + $provider = $this->container->query($initialState->getService()); |
|
| 122 | + } catch (QueryException $e) { |
|
| 123 | + // Log an continue. We can be fault tolerant here. |
|
| 124 | + $this->logger->error('Could not load initial state provider dynamically: ' . $e->getMessage(), [ |
|
| 125 | + 'exception' => $e, |
|
| 126 | + 'app' => $initialState->getAppId(), |
|
| 127 | + ]); |
|
| 128 | + continue; |
|
| 129 | + } |
|
| 130 | + |
|
| 131 | + if (!($provider instanceof InitialStateProvider)) { |
|
| 132 | + // Log an continue. We can be fault tolerant here. |
|
| 133 | + $this->logger->error('Initial state provider is not an InitialStateProvider instance: ' . $initialState->getService(), [ |
|
| 134 | + 'app' => $initialState->getAppId(), |
|
| 135 | + ]); |
|
| 136 | + } |
|
| 137 | + |
|
| 138 | + $this->provideInitialState($initialState->getAppId(), $provider->getKey(), $provider); |
|
| 139 | + } |
|
| 140 | + } |
|
| 141 | + |
|
| 142 | + public function getInitialStates(): array { |
|
| 143 | + $this->invokeLazyStateCallbacks(); |
|
| 144 | + $this->loadLazyStates(); |
|
| 145 | + |
|
| 146 | + $appStates = []; |
|
| 147 | + foreach ($this->states as $app => $states) { |
|
| 148 | + foreach ($states as $key => $value) { |
|
| 149 | + $appStates["$app-$key"] = $value; |
|
| 150 | + } |
|
| 151 | + } |
|
| 152 | + return $appStates; |
|
| 153 | + } |
|
| 154 | 154 | } |
@@ -67,12 +67,12 @@ discard block |
||
| 67 | 67 | try { |
| 68 | 68 | $this->states[$appName][$key] = json_encode($data, JSON_THROW_ON_ERROR); |
| 69 | 69 | } catch (\JsonException $e) { |
| 70 | - $this->logger->error('Invalid '. $key . ' data provided to provideInitialState by ' . $appName, ['exception' => $e]); |
|
| 70 | + $this->logger->error('Invalid '.$key.' data provided to provideInitialState by '.$appName, ['exception' => $e]); |
|
| 71 | 71 | } |
| 72 | 72 | return; |
| 73 | 73 | } |
| 74 | 74 | |
| 75 | - $this->logger->warning('Invalid '. $key . ' data provided to provideInitialState by ' . $appName); |
|
| 75 | + $this->logger->warning('Invalid '.$key.' data provided to provideInitialState by '.$appName); |
|
| 76 | 76 | } |
| 77 | 77 | |
| 78 | 78 | public function provideLazyInitialState(string $appName, string $key, Closure $closure): void { |
@@ -121,7 +121,7 @@ discard block |
||
| 121 | 121 | $provider = $this->container->query($initialState->getService()); |
| 122 | 122 | } catch (QueryException $e) { |
| 123 | 123 | // Log an continue. We can be fault tolerant here. |
| 124 | - $this->logger->error('Could not load initial state provider dynamically: ' . $e->getMessage(), [ |
|
| 124 | + $this->logger->error('Could not load initial state provider dynamically: '.$e->getMessage(), [ |
|
| 125 | 125 | 'exception' => $e, |
| 126 | 126 | 'app' => $initialState->getAppId(), |
| 127 | 127 | ]); |
@@ -130,7 +130,7 @@ discard block |
||
| 130 | 130 | |
| 131 | 131 | if (!($provider instanceof InitialStateProvider)) { |
| 132 | 132 | // Log an continue. We can be fault tolerant here. |
| 133 | - $this->logger->error('Initial state provider is not an InitialStateProvider instance: ' . $initialState->getService(), [ |
|
| 133 | + $this->logger->error('Initial state provider is not an InitialStateProvider instance: '.$initialState->getService(), [ |
|
| 134 | 134 | 'app' => $initialState->getAppId(), |
| 135 | 135 | ]); |
| 136 | 136 | } |