@@ -25,7 +25,7 @@ final class DistributedServiceMap implements DefinedObject
2525{
2626 /**
2727 * @param array<string, string> $commandMapping - service name -> channel name (for command routing)
28- * @param array<string, array{keys: ?array<string>, exclude: array<string>}> $eventSubscriptions - channel name -> ['keys' => [...] or null, 'exclude' => [...]]
28+ * @param array<string, array{keys: ?array<string>, exclude: array<string>, include: array<string> }> $eventSubscriptions - channel name -> ['keys' => [...] or null, 'exclude' => [...], 'include ' => [...]]
2929 * @param array<object> $distributedBusAnnotations
3030 * @param bool|null $legacyMode - null = not set, true = legacy (withServiceMapping), false = new API (withCommandMapping/withEventMapping)
3131 */
@@ -58,6 +58,7 @@ public function withServiceMapping(string $serviceName, string $channelName, ?ar
5858 $ self ->eventSubscriptions [$ channelName ] = [
5959 'keys ' => $ subscriptionRoutingKeys ,
6060 'exclude ' => [],
61+ 'include ' => [],
6162 ];
6263
6364 return $ self ;
@@ -83,17 +84,26 @@ public function withCommandMapping(string $targetServiceName, string $channelNam
8384 *
8485 * @param string $channelName Target channel to send events to
8586 * @param array<string> $subscriptionKeys Routing key patterns to match
86- * @param array<string> $excludeEventsFromServices Service names whose events should NOT be sent to this channel
87+ * @param array<string> $excludePublishingServices Service names whose events should NOT be sent to this channel
88+ * @param array<string> $includePublishingServices Service names whose events should ONLY be sent to this channel (whitelist)
8789 */
88- public function withEventMapping (string $ channelName , array $ subscriptionKeys , array $ excludeEventsFromServices = []): self
90+ public function withEventMapping (string $ channelName , array $ subscriptionKeys , array $ excludePublishingServices = [], array $ includePublishingServices = []): self
8991 {
92+ if ($ excludePublishingServices !== [] && $ includePublishingServices !== []) {
93+ throw ConfigurationException::create (
94+ "Cannot use both 'excludePublishingServices' and 'includePublishingServices' in the same event mapping for channel ' {$ channelName }'. " .
95+ 'These parameters are mutually exclusive - use either exclude (blacklist) or include (whitelist), not both. '
96+ );
97+ }
98+
9099 $ self = clone $ this ;
91100 $ self ->assertNotInLegacyMode ('withEventMapping ' );
92101 $ self ->legacyMode = false ;
93102
94103 $ self ->eventSubscriptions [$ channelName ] = [
95104 'keys ' => $ subscriptionKeys ,
96- 'exclude ' => $ excludeEventsFromServices ,
105+ 'exclude ' => $ excludePublishingServices ,
106+ 'include ' => $ includePublishingServices ,
97107 ];
98108
99109 return $ self ;
@@ -153,7 +163,7 @@ public function getAllChannelNamesBesides(string $serviceName, string $routingKe
153163
154164 /**
155165 * NEW MODE ONLY - Get all subscription channels for an event.
156- * Uses explicit exclude list from eventSubscriptions config.
166+ * Uses explicit exclude/include list from eventSubscriptions config.
157167 *
158168 * @param string $sourceServiceName The service publishing the event
159169 * @param string $routingKey The event routing key
@@ -166,11 +176,16 @@ public function getAllSubscriptionChannels(string $sourceServiceName, string $ro
166176 foreach ($ this ->eventSubscriptions as $ channel => $ config ) {
167177 $ keys = $ config ['keys ' ];
168178 $ exclude = $ config ['exclude ' ];
179+ $ include = $ config ['include ' ];
169180
170181 if (in_array ($ sourceServiceName , $ exclude , true )) {
171182 continue ;
172183 }
173184
185+ if ($ include !== [] && ! in_array ($ sourceServiceName , $ include , true )) {
186+ continue ;
187+ }
188+
174189 foreach ($ keys as $ subscriptionEventFilter ) {
175190 if (BusRoutingMap::globMatch ($ subscriptionEventFilter , $ routingKey )) {
176191 $ filteredChannels [] = $ channel ;
0 commit comments