18
18
19
19
import org .apache .rocketmq .common .message .MessageQueue ;
20
20
import org .apache .rocketmq .streams .core .common .Constant ;
21
+ import org .apache .rocketmq .streams .core .exception .RStreamsException ;
21
22
import org .apache .rocketmq .streams .core .exception .RecoverStateStoreThrowable ;
22
23
import org .apache .rocketmq .streams .core .function .ValueJoinAction ;
23
24
import org .apache .rocketmq .streams .core .metadata .Data ;
33
34
import org .apache .rocketmq .streams .core .window .WindowStore ;
34
35
import org .apache .rocketmq .streams .core .util .Pair ;
35
36
import org .apache .rocketmq .streams .core .util .Utils ;
37
+ import org .apache .rocketmq .streams .core .window .fire .JoinWindowFire ;
36
38
import org .slf4j .Logger ;
37
39
import org .slf4j .LoggerFactory ;
38
40
39
41
import java .util .Comparator ;
40
42
import java .util .List ;
41
43
import java .util .Properties ;
44
+ import java .util .concurrent .atomic .AtomicReference ;
42
45
import java .util .function .Supplier ;
43
46
44
47
public class JoinWindowAggregateSupplier <K , V1 , V2 , OUT > implements Supplier <Processor <? super OUT >> {
@@ -84,31 +87,49 @@ public void preProcess(StreamContext<Object> context) throws RecoverStateStoreTh
84
87
super .preProcess (context );
85
88
leftWindowStore = new WindowStore <>(super .waitStateReplay (), WindowState ::byte2WindowState , WindowState ::windowState2Byte );
86
89
rightWindowStore = new WindowStore <>(super .waitStateReplay (), WindowState ::byte2WindowState , WindowState ::windowState2Byte );
87
- String stateTopicName = getSourceTopic () + Constant .STATE_TOPIC_SUFFIX ;
88
- this .stateTopicMessageQueue = new MessageQueue (stateTopicName , getSourceBrokerName (), getSourceQueueId ());
89
- }
90
90
91
+ this .idleWindowScaner = context .getDefaultWindowScaner ();
92
+
93
+ String stateTopicName = context .getSourceTopic () + Constant .STATE_TOPIC_SUFFIX ;
94
+ this .stateTopicMessageQueue = new MessageQueue (stateTopicName , context .getSourceBrokerName (), context .getSourceQueueId ());
95
+
96
+ this .joinWindowFire = new JoinWindowFire <>(joinType ,
97
+ this .stateTopicMessageQueue ,
98
+ context .copy (),
99
+ joinAction ,
100
+ leftWindowStore ,
101
+ rightWindowStore ,
102
+ this ::watermark );
103
+ }
91
104
92
105
@ Override
93
106
public void process (Object data ) throws Throwable {
94
107
95
108
Object key = this .context .getKey ();
96
109
long time = this .context .getDataTime ();
97
110
Properties header = this .context .getHeader ();
98
- long watermark = this .context . getWatermark ( );
111
+ long watermark = this .watermark ( time , stateTopicMessageQueue );
99
112
WindowInfo .JoinStream stream = (WindowInfo .JoinStream ) header .get (Constant .STREAM_TAG );
100
113
101
114
if (time < watermark ) {
102
115
//已经触发,丢弃数据
116
+ logger .warn ("discard data:[{}], window has been fired. maxFiredWindowEnd:{}, time of data:{}, watermark:{}" ,
117
+ data , watermark , watermark , time );
103
118
return ;
104
119
}
105
120
106
121
StreamType streamType = stream .getStreamType ();
107
-
122
+ if (streamType == null ) {
123
+ String format = String .format ("StreamType is empty, data:%s" , data );
124
+ throw new IllegalStateException (format );
125
+ }
108
126
109
127
store (key , data , time , streamType );
110
128
111
- fire (watermark , streamType );
129
+ List <WindowKey > fire = this .joinWindowFire .fire (this .name , watermark , streamType );
130
+ for (WindowKey windowKey : fire ) {
131
+ this .idleWindowScaner .removeWindowKey (windowKey );
132
+ }
112
133
}
113
134
114
135
@@ -124,110 +145,16 @@ private void store(Object key, Object data, long time, StreamType streamType) th
124
145
case LEFT_STREAM :
125
146
WindowState <K , V1 > leftState = new WindowState <>((K ) key , (V1 ) data , time );
126
147
this .leftWindowStore .put (stateTopicMessageQueue , windowKey , leftState );
148
+ this .idleWindowScaner .putJoinWindowCallback (windowKey , joinWindowFire );
127
149
break ;
128
150
case RIGHT_STREAM :
129
151
WindowState <K , V2 > rightState = new WindowState <>((K ) key , (V2 ) data , time );
130
152
this .rightWindowStore .put (stateTopicMessageQueue , windowKey , rightState );
153
+ this .idleWindowScaner .putJoinWindowCallback (windowKey , joinWindowFire );
131
154
break ;
132
155
}
133
156
}
134
- }
135
-
136
- private void fire (long watermark , StreamType streamType ) throws Throwable {
137
- String leftWindow = Utils .buildKey (this .name , StreamType .LEFT_STREAM .name ());
138
- WindowKey leftWindowKey = new WindowKey (leftWindow , null , watermark , 0L );
139
- List <Pair <WindowKey , WindowState <K , V1 >>> leftPairs = this .leftWindowStore .searchLessThanWatermark (leftWindowKey );
140
-
141
- String rightWindow = Utils .buildKey (this .name , StreamType .RIGHT_STREAM .name ());
142
- WindowKey rightWindowKey = new WindowKey (rightWindow , null , watermark , 0L );
143
- List <Pair <WindowKey , WindowState <K , V2 >>> rightPairs = this .rightWindowStore .searchLessThanWatermark (rightWindowKey );
144
-
145
-
146
- if (leftPairs .size () == 0 && rightPairs .size () == 0 ) {
147
- return ;
148
- }
149
-
150
- leftPairs .sort (Comparator .comparing (pair -> {
151
- WindowKey key = pair .getKey ();
152
- return key .getWindowEnd ();
153
- }));
154
- rightPairs .sort (Comparator .comparing (pair -> {
155
- WindowKey key = pair .getKey ();
156
- return key .getWindowEnd ();
157
- }));
158
-
159
- switch (joinType ) {
160
- case INNER_JOIN :
161
- //匹配上才触发
162
- for (Pair <WindowKey , WindowState <K , V1 >> leftPair : leftPairs ) {
163
- String leftPrefix = leftPair .getKey ().getKeyAndWindow ();
164
-
165
- for (Pair <WindowKey , WindowState <K , V2 >> rightPair : rightPairs ) {
166
- String rightPrefix = rightPair .getKey ().getKeyAndWindow ();
167
-
168
- //相同window中相同key,聚合
169
- if (leftPrefix .equals (rightPrefix )) {
170
- //do fire
171
- V1 o1 = leftPair .getValue ().getValue ();
172
- V2 o2 = rightPair .getValue ().getValue ();
173
-
174
- OUT out = this .joinAction .apply (o1 , o2 );
175
-
176
- Properties header = this .context .getHeader ();
177
- header .put (Constant .WINDOW_START_TIME , leftPair .getKey ().getWindowStart ());
178
- header .put (Constant .WINDOW_END_TIME , leftPair .getKey ().getWindowEnd ());
179
- Data <K , OUT > result = new Data <>(this .context .getKey (), out , this .context .getDataTime (), header );
180
- Data <K , Object > convert = super .convert (result );
181
- this .context .forward (convert );
182
- }
183
- }
184
- }
185
- break ;
186
- case LEFT_JOIN :
187
- switch (streamType ) {
188
- case LEFT_STREAM :
189
- //左流全部触发,不管右流匹配上没
190
- for (Pair <WindowKey , WindowState <K , V1 >> leftPair : leftPairs ) {
191
- String leftPrefix = leftPair .getKey ().getKeyAndWindow ();
192
- Pair <WindowKey , WindowState <K , V2 >> targetPair = null ;
193
- for (Pair <WindowKey , WindowState <K , V2 >> rightPair : rightPairs ) {
194
- if (rightPair .getKey ().getKeyAndWindow ().equals (leftPrefix )) {
195
- targetPair = rightPair ;
196
- break ;
197
- }
198
- }
199
-
200
- //fire
201
- V1 o1 = leftPair .getValue ().getValue ();
202
- V2 o2 = null ;
203
- if (targetPair != null ) {
204
- o2 = targetPair .getValue ().getValue ();
205
- }
206
-
207
- OUT out = this .joinAction .apply (o1 , o2 );
208
- Properties header = this .context .getHeader ();
209
- header .put (Constant .WINDOW_START_TIME , leftPair .getKey ().getWindowStart ());
210
- header .put (Constant .WINDOW_END_TIME , leftPair .getKey ().getWindowEnd ());
211
- Data <K , OUT > result = new Data <>(this .context .getKey (), out , this .context .getDataTime (), header );
212
- Data <K , Object > convert = super .convert (result );
213
- this .context .forward (convert );
214
- }
215
- break ;
216
- case RIGHT_STREAM :
217
- //do nothing.
218
- }
219
- break ;
220
- }
221
-
222
- //删除状态
223
- for (Pair <WindowKey , WindowState <K , V1 >> leftPair : leftPairs ) {
224
- this .leftWindowStore .deleteByKey (leftPair .getKey ());
225
- }
226
157
227
- for (Pair <WindowKey , WindowState <K , V2 >> rightPair : rightPairs ) {
228
- this .rightWindowStore .deleteByKey (rightPair .getKey ());
229
- }
230
158
}
231
-
232
159
}
233
160
}
0 commit comments