@@ -39,6 +39,8 @@ protected function configure(): void
3939 new InputArgument ('id ' , InputArgument::OPTIONAL , 'Specific message id to show ' ),
4040 new InputOption ('max ' , null , InputOption::VALUE_REQUIRED , 'Maximum number of messages to list ' , 50 ),
4141 new InputOption ('transport ' , null , InputOption::VALUE_OPTIONAL , 'Use a specific failure transport ' , self ::DEFAULT_TRANSPORT_OPTION ),
42+ new InputOption ('stats ' , null , InputOption::VALUE_NONE , 'Display the message count by class ' ),
43+ new InputOption ('class-filter ' , null , InputOption::VALUE_REQUIRED , 'Filter by a specific class name ' ),
4244 ])
4345 ->setHelp (<<<'EOF'
4446The <info>%command.name%</info> shows message that are pending in the failure transport.
@@ -77,23 +79,36 @@ protected function execute(InputInterface $input, OutputInterface $output): int
7779 throw new RuntimeException (sprintf ('The "%s" receiver does not support listing or showing specific messages. ' , $ failureTransportName ));
7880 }
7981
80- if (null === $ id = $ input ->getArgument ('id ' )) {
81- $ this ->listMessages ($ failureTransportName , $ io , $ input ->getOption ('max ' ));
82+ if ($ input ->getOption ('stats ' )) {
83+ $ this ->listMessagesPerClass ($ failureTransportName , $ io , $ input ->getOption ('max ' ));
84+ } elseif (null === $ id = $ input ->getArgument ('id ' )) {
85+ $ this ->listMessages ($ failureTransportName , $ io , $ input ->getOption ('max ' ), $ input ->getOption ('class-filter ' ));
8286 } else {
8387 $ this ->showMessage ($ failureTransportName , $ id , $ io );
8488 }
8589
8690 return 0 ;
8791 }
8892
89- private function listMessages (?string $ failedTransportName , SymfonyStyle $ io , int $ max )
93+ private function listMessages (?string $ failedTransportName , SymfonyStyle $ io , int $ max, string $ classFilter = null )
9094 {
9195 /** @var ListableReceiverInterface $receiver */
9296 $ receiver = $ this ->getReceiver ($ failedTransportName );
9397 $ envelopes = $ receiver ->all ($ max );
9498
9599 $ rows = [];
100+
101+ if ($ classFilter ) {
102+ $ io ->comment (sprintf ('Displaying only \'%s \' messages ' , $ classFilter ));
103+ }
104+
96105 foreach ($ envelopes as $ envelope ) {
106+ $ currentClassName = \get_class ($ envelope ->getMessage ());
107+
108+ if ($ classFilter && $ classFilter !== $ currentClassName ) {
109+ continue ;
110+ }
111+
97112 /** @var RedeliveryStamp|null $lastRedeliveryStamp */
98113 $ lastRedeliveryStamp = $ envelope ->last (RedeliveryStamp::class);
99114 /** @var ErrorDetailsStamp|null $lastErrorDetailsStamp */
@@ -106,27 +121,58 @@ private function listMessages(?string $failedTransportName, SymfonyStyle $io, in
106121
107122 $ rows [] = [
108123 $ this ->getMessageId ($ envelope ),
109- \get_class ( $ envelope -> getMessage ()) ,
124+ $ currentClassName ,
110125 null === $ lastRedeliveryStamp ? '' : $ lastRedeliveryStamp ->getRedeliveredAt ()->format ('Y-m-d H:i:s ' ),
111126 $ errorMessage ,
112127 ];
113128 }
114129
115- if (0 === \count ($ rows )) {
130+ $ rowsCount = \count ($ rows );
131+
132+ if (0 === $ rowsCount ) {
116133 $ io ->success ('No failed messages were found. ' );
117134
118135 return ;
119136 }
120137
121138 $ io ->table (['Id ' , 'Class ' , 'Failed at ' , 'Error ' ], $ rows );
122139
123- if (\count ( $ rows ) === $ max ) {
140+ if ($ rowsCount === $ max ) {
124141 $ io ->comment (sprintf ('Showing first %d messages. ' , $ max ));
142+ } elseif ($ classFilter ) {
143+ $ io ->comment (sprintf ('Showing %d message(s). ' , $ rowsCount ));
125144 }
126145
127146 $ io ->comment (sprintf ('Run <comment>messenger:failed:show {id} --transport=%s -vv</comment> to see message details. ' , $ failedTransportName ));
128147 }
129148
149+ private function listMessagesPerClass (?string $ failedTransportName , SymfonyStyle $ io , int $ max )
150+ {
151+ /** @var ListableReceiverInterface $receiver */
152+ $ receiver = $ this ->getReceiver ($ failedTransportName );
153+ $ envelopes = $ receiver ->all ($ max );
154+
155+ $ countPerClass = [];
156+
157+ foreach ($ envelopes as $ envelope ) {
158+ $ c = \get_class ($ envelope ->getMessage ());
159+
160+ if (!isset ($ countPerClass [$ c ])) {
161+ $ countPerClass [$ c ] = [$ c , 0 ];
162+ }
163+
164+ ++$ countPerClass [$ c ][1 ];
165+ }
166+
167+ if (0 === \count ($ countPerClass )) {
168+ $ io ->success ('No failed messages were found. ' );
169+
170+ return ;
171+ }
172+
173+ $ io ->table (['Class ' , 'Count ' ], $ countPerClass );
174+ }
175+
130176 private function showMessage (?string $ failedTransportName , string $ id , SymfonyStyle $ io )
131177 {
132178 /** @var ListableReceiverInterface $receiver */
0 commit comments