-
Notifications
You must be signed in to change notification settings - Fork 2
/
debug_event_dispatcher.cr
121 lines (105 loc) · 4.42 KB
/
debug_event_dispatcher.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
@[ACONA::AsCommand("debug:event-dispatcher", description: "Display configured listeners for an application")]
@[ADI::Register]
# Utility command to allow viewing information about an `AED::EventDispatcherInterface`.
# Includes the type/method of each event listener, along with the order they run in based on their priority.
# Accepts an optional argument to allow filtering the list to a specific event, or ones that contain the provided string.
#
# ```text
# $ ./bin/console debug:event-dispatcher
# Registered Listeners Grouped by Event
# =====================================
#
# Athena::Framework::Events::Action event
# ---------------------------------------
#
# ------- -------------------------------------------------------- ----------
# Order Callable Priority
# ------- -------------------------------------------------------- ----------
# #1 Athena::Framework::Listeners::ParamFetcher#on_action 5
# ------- -------------------------------------------------------- ----------
#
# Athena::Framework::Events::Exception event
# ------------------------------------------
#
# ------- -------------------------------------------------- ----------
# Order Callable Priority
# ------- -------------------------------------------------- ----------
# #1 Athena::Framework::Listeners::Error#on_exception -50
# ------- -------------------------------------------------- ----------
#
# Athena::Framework::Events::Request event
# ----------------------------------------
#
# ------- -------------------------------------------------- ----------
# Order Callable Priority
# ------- -------------------------------------------------- ----------
# #1 Athena::Framework::Listeners::CORS#on_request 250
# #2 Athena::Framework::Listeners::Format#on_request 34
# #3 Athena::Framework::Listeners::Routing#on_request 32
# ------- -------------------------------------------------- ----------
#
# ...
# ```
#
# TODO: Support dedicated `AED::EventDispatcherInterface` services other than the default.
class Athena::Framework::Commands::DebugEventDispatcher < ACON::Command
def initialize(
@dispatcher : AED::EventDispatcherInterface
)
super()
end
protected def configure : Nil
self
.argument("event", description: "An event name or a part of the event name") { @dispatcher.listeners.keys.map &.to_s }
.option("format", value_mode: :required, description: "The output format (txt)", default: "txt") { ACON::Helper::Descriptor.new.formats }
.option("raw", nil, :none, "To output raw command help")
end
protected def execute(input : ACON::Input::Interface, output : ACON::Output::Interface) : ACON::Command::Status
style = ACON::Style::Athena.new input, output
# TODO: Allow resolving a specific dispatcher service
dispatcher = @dispatcher
event_class_map = dispatcher.listeners.each_key.each_with_object({} of String => AED::Event.class) do |event, map|
map[event.to_s] = event
end
event_class = nil
event_classes = nil
if event = input.argument "event"
e = event_class_map[event]?
if e && dispatcher.has_listeners? e
event_class = e
else
events = self.search_for_event dispatcher, event
if events.empty?
style.error_style.warning "The event '#{event}' does not have any registered listeners."
return Status::SUCCESS
elsif 1 == events.size
event_class = events.first
else
event_classes = events
end
end
end
helper = Athena::Framework::Console::Helper::Descriptor.new
helper
.describe(
style,
dispatcher,
ATH::Console::Descriptor::EventDispatcherContext.new(
output: style,
event_class: event_class,
event_classes: event_classes,
format: input.option("format", String),
raw_text: input.option("raw", Bool),
)
)
Status::SUCCESS
end
private def search_for_event(dispatcher : AED::EventDispatcherInterface, event : String) : Array(AED::Event.class)
event_class_string = event.downcase
matching_events = [] of AED::Event.class
dispatcher.listeners.each_key.each do |event_class|
matching_events << event_class if event_class.to_s.downcase.includes? event_class_string
end
matching_events
end
end