21
21
import java .util .concurrent .*;
22
22
import java .util .concurrent .atomic .AtomicBoolean ;
23
23
import java .util .concurrent .atomic .AtomicReference ;
24
+ import java .util .function .Consumer ;
24
25
25
26
final class RecordingTopologyListener implements TopologyListener , AutoCloseable {
26
27
27
- private final EventLoop eventLoop ;
28
- private final Map <String , ExchangeSpec > exchanges = new LinkedHashMap <>();
29
- private final Map <String , QueueSpec > queues = new LinkedHashMap <>();
30
- private final Set <BindingSpec > bindings = new LinkedHashSet <>();
31
- private final Map <Long , ConsumerSpec > consumers = new LinkedHashMap <>();
28
+ private final EventLoop <State > eventLoop ;
29
+
32
30
private final AtomicBoolean closed = new AtomicBoolean (false );
33
31
34
32
RecordingTopologyListener (ExecutorService executorService ) {
35
- this .eventLoop = new EventLoop ("topology" , executorService );
33
+ this .eventLoop = new EventLoop <>(State ::new , "topology" , executorService );
34
+ }
35
+
36
+ private static class State {
37
+
38
+ private final Map <String , ExchangeSpec > exchanges = new LinkedHashMap <>();
39
+ private final Map <String , QueueSpec > queues = new LinkedHashMap <>();
40
+ private final Set <BindingSpec > bindings = new LinkedHashSet <>();
41
+ private final Map <Long , ConsumerSpec > consumers = new LinkedHashMap <>();
36
42
}
37
43
38
44
@ Override
39
45
public void exchangeDeclared (AmqpExchangeSpecification specification ) {
40
- this .submit (() -> this .exchanges .put (specification .name (), new ExchangeSpec (specification )));
46
+ this .submit (s -> s .exchanges .put (specification .name (), new ExchangeSpec (specification )));
41
47
}
42
48
43
49
@ Override
44
50
public void exchangeDeleted (String name ) {
45
51
this .submit (
46
- () -> {
47
- this .exchanges .remove (name );
48
- Set <BindingSpec > deletedBindings = this .deleteBindings (name , true );
49
- this .deleteAutoDeleteExchanges (deletedBindings );
52
+ s -> {
53
+ s .exchanges .remove (name );
54
+ Set <BindingSpec > deletedBindings = this .deleteBindings (s , name , true );
55
+ this .deleteAutoDeleteExchanges (s , deletedBindings );
50
56
});
51
57
}
52
58
53
59
@ Override
54
60
public void queueDeclared (AmqpQueueSpecification specification ) {
55
- this .submit (() -> this .queues .put (specification .name (), new QueueSpec (specification )));
61
+ this .submit (s -> s .queues .put (specification .name (), new QueueSpec (specification )));
56
62
}
57
63
58
64
@ Override
59
65
public void queueDeleted (String name ) {
60
66
this .submit (
61
- () -> {
62
- this .queues .remove (name );
63
- Set <BindingSpec > deletedBindings = this .deleteBindings (name , false );
64
- this .deleteAutoDeleteExchanges (deletedBindings );
67
+ s -> {
68
+ s .queues .remove (name );
69
+ Set <BindingSpec > deletedBindings = this .deleteBindings (s , name , false );
70
+ this .deleteAutoDeleteExchanges (s , deletedBindings );
65
71
});
66
72
}
67
73
68
74
@ Override
69
75
public void bindingDeclared (AmqpBindingManagement .AmqpBindingSpecification specification ) {
70
- this .submit (() -> this .bindings .add (new BindingSpec (specification .state ())));
76
+ this .submit (s -> s .bindings .add (new BindingSpec (specification .state ())));
71
77
}
72
78
73
79
@ Override
74
80
public void bindingDeleted (AmqpBindingManagement .AmqpUnbindSpecification specification ) {
75
81
this .submit (
76
- () -> {
82
+ s -> {
77
83
BindingSpec spec = new BindingSpec (specification .state ());
78
- this .bindings .remove (spec );
79
- this .deleteAutoDeleteExchanges (Collections .singleton (spec ));
84
+ s .bindings .remove (spec );
85
+ this .deleteAutoDeleteExchanges (s , Collections .singleton (spec ));
80
86
});
81
87
}
82
88
83
89
@ Override
84
90
public void consumerCreated (long id , String queue ) {
85
- this .submit (() -> this .consumers .put (id , new ConsumerSpec (id , queue )));
91
+ this .submit (s -> s .consumers .put (id , new ConsumerSpec (id , queue )));
86
92
}
87
93
88
94
@ Override
89
95
public void consumerDeleted (long id , String queue ) {
90
96
this .submit (
91
- () -> {
92
- this .consumers .remove (id );
97
+ s -> {
98
+ s .consumers .remove (id );
93
99
// if there's no consumer anymore on the queue, delete it if it's auto-delete
94
100
boolean atLeastOneConsumerOnQueue =
95
- this .consumers .values ().stream ().anyMatch (spec -> spec .queue .equals (queue ));
101
+ s .consumers .values ().stream ().anyMatch (spec -> spec .queue .equals (queue ));
96
102
if (!atLeastOneConsumerOnQueue ) {
97
- QueueSpec queueSpec = this .queues .get (queue );
103
+ QueueSpec queueSpec = s .queues .get (queue );
98
104
if (queueSpec != null && queueSpec .autoDelete ) {
99
105
this .queueDeleted (queue );
100
106
}
@@ -109,16 +115,16 @@ public void close() {
109
115
}
110
116
}
111
117
112
- private void submit (Runnable task ) {
118
+ private void submit (Consumer < State > task ) {
113
119
if (!this .closed .get ()) {
114
120
this .eventLoop .submit (task );
115
121
}
116
122
}
117
123
118
- private Set <BindingSpec > deleteBindings (String name , boolean exchange ) {
124
+ private Set <BindingSpec > deleteBindings (State s , String name , boolean exchange ) {
119
125
Set <BindingSpec > deletedBindings = new LinkedHashSet <>();
120
126
// delete bindings that depend on this exchange or queue
121
- Iterator <BindingSpec > iterator = this .bindings .iterator ();
127
+ Iterator <BindingSpec > iterator = s .bindings .iterator ();
122
128
while (iterator .hasNext ()) {
123
129
BindingSpec spec = iterator .next ();
124
130
if (spec .isInvolved (name , exchange )) {
@@ -129,57 +135,37 @@ private Set<BindingSpec> deleteBindings(String name, boolean exchange) {
129
135
return deletedBindings ;
130
136
}
131
137
132
- private void deleteAutoDeleteExchanges (Set <BindingSpec > deletedBindings ) {
138
+ private void deleteAutoDeleteExchanges (State s , Set <BindingSpec > deletedBindings ) {
133
139
// delete auto-delete exchanges which are no longer sources in any bindings
134
140
for (BindingSpec binding : deletedBindings ) {
135
141
String source = binding .source ;
136
142
boolean exchangeStillSource ;
137
- exchangeStillSource = this .bindings .stream ().anyMatch (b -> b .source .equals (source ));
143
+ exchangeStillSource = s .bindings .stream ().anyMatch (b -> b .source .equals (source ));
138
144
139
145
if (!exchangeStillSource ) {
140
- ExchangeSpec exchange = this .exchanges .get (source );
146
+ ExchangeSpec exchange = s .exchanges .get (source );
141
147
if (exchange != null && exchange .autoDelete ) {
142
148
exchangeDeleted (exchange .name );
143
149
}
144
150
}
145
151
}
146
152
}
147
153
148
- Map <String , ExchangeSpec > exchanges () {
149
- return new LinkedHashMap <>(this .exchanges );
150
- }
151
-
152
- Map <String , QueueSpec > queues () {
153
- return new LinkedHashMap <>(this .queues );
154
- }
155
-
156
154
void accept (Visitor visitor ) {
157
155
AtomicReference <List <ExchangeSpec >> exchangeCopy = new AtomicReference <>();
158
156
AtomicReference <List <QueueSpec >> queueCopy = new AtomicReference <>();
159
157
AtomicReference <Set <BindingSpec >> bindingCopy = new AtomicReference <>();
160
158
submit (
161
- () -> {
162
- exchangeCopy .set (new ArrayList <>(this .exchanges .values ()));
163
- queueCopy .set (new ArrayList <>(this .queues .values ()));
164
- bindingCopy .set (new LinkedHashSet <>(this .bindings ));
159
+ s -> {
160
+ exchangeCopy .set (new ArrayList <>(s .exchanges .values ()));
161
+ queueCopy .set (new ArrayList <>(s .queues .values ()));
162
+ bindingCopy .set (new LinkedHashSet <>(s .bindings ));
165
163
});
166
164
visitor .visitExchanges (exchangeCopy .get ());
167
165
visitor .visitQueues (queueCopy .get ());
168
166
visitor .visitBindings (bindingCopy .get ());
169
167
}
170
168
171
- int bindingCount () {
172
- return this .bindings .size ();
173
- }
174
-
175
- int exchangeCount () {
176
- return this .exchanges .size ();
177
- }
178
-
179
- int queueCount () {
180
- return this .queues .size ();
181
- }
182
-
183
169
static class ExchangeSpec {
184
170
185
171
private final String name ;
@@ -340,4 +326,30 @@ interface Visitor {
340
326
341
327
void visitBindings (Collection <BindingSpec > bindings );
342
328
}
329
+
330
+ // for test assertions
331
+
332
+ private State state () {
333
+ return this .eventLoop .state ();
334
+ }
335
+
336
+ Map <String , ExchangeSpec > exchanges () {
337
+ return new LinkedHashMap <>(state ().exchanges );
338
+ }
339
+
340
+ Map <String , QueueSpec > queues () {
341
+ return new LinkedHashMap <>(state ().queues );
342
+ }
343
+
344
+ int bindingCount () {
345
+ return state ().bindings .size ();
346
+ }
347
+
348
+ int exchangeCount () {
349
+ return state ().exchanges .size ();
350
+ }
351
+
352
+ int queueCount () {
353
+ return state ().queues .size ();
354
+ }
343
355
}
0 commit comments