@@ -44,6 +44,7 @@ import org.apache.curator.framework.CuratorFramework
44
44
import org .joda .time .DateTimeZone
45
45
import org .joda .time .DateTime
46
46
import org .joda .time .Interval
47
+ import org .joda .time .chrono .ISOChronology
47
48
import org .scala_tools .time .Implicits ._
48
49
import org .scalatest .BeforeAndAfter
49
50
import org .scalatest .FunSuite
@@ -68,7 +69,14 @@ class ClusteredBeamTest extends FunSuite with CuratorRequiringSuite with BeforeA
68
69
SimpleEvent (new DateTime (" 2012-01-01T01:10Z" ), Map (" foo" -> " e" )),
69
70
SimpleEvent (new DateTime (" 2012-01-01T01:20Z" ), Map (" foo" -> " f" )),
70
71
SimpleEvent (new DateTime (" 2012-01-01T03:05Z" ), Map (" foo" -> " g" )),
71
- SimpleEvent (new DateTime (" 2012-01-01T03:20Z" ), Map (" foo" -> " h" ))
72
+ SimpleEvent (new DateTime (" 2012-01-01T03:20Z" ), Map (" foo" -> " h" )),
73
+ SimpleEvent (new DateTime (" 2012-01-01T01:05Z" ), Map (" foo" -> " i" )),
74
+ SimpleEvent (new DateTime (" 2012-01-01T01:06Z" ), Map (" foo" -> " j" )),
75
+ SimpleEvent (new DateTime (" 2012-01-01T01:07Z" ), Map (" foo" -> " k" )),
76
+ SimpleEvent (new DateTime (" 2012-01-01T01:06Z" ), Map (" foo" -> " l" )),
77
+ SimpleEvent (new DateTime (" 2012-01-01T01:05Z" ), Map (" foo" -> " m" )),
78
+ SimpleEvent (new DateTime (" 2012-01-01T01:09Z" ), Map (" foo" -> " n" )),
79
+ SimpleEvent (new DateTime (" 2012-01-01T01:10Z" ), Map (" foo" -> " o" ))
72
80
) map {
73
81
x => x.fields(" foo" ) -> x
74
82
}).toMap
@@ -79,14 +87,18 @@ class ClusteredBeamTest extends FunSuite with CuratorRequiringSuite with BeforeA
79
87
val localZone = new DateTime ().getZone
80
88
81
89
def buffers = _lock.synchronized {
82
- _buffers.values.map(x => (x.timestamp.withZone(localZone), x.partition, x.open, x.buffer.toSeq)).toSet
90
+ _buffers.values.map(x => (x.interval.start.withZone(localZone), x.partition, x.open, x.buffer.toSeq)).toSet
91
+ }
92
+
93
+ def buffersWithInterval = _lock.synchronized {
94
+ _buffers.values.map(x => (x.interval, x.partition, x.open, x.buffer.toSeq)).toSet
83
95
}
84
96
85
97
def beamsList = _lock.synchronized {
86
98
_beams.toList
87
99
}
88
100
89
- class EventBuffer (val timestamp : DateTime , val partition : Int )
101
+ class EventBuffer (val interval : Interval , val partition : Int )
90
102
{
91
103
val buffer : mutable.Buffer [SimpleEvent ] = mutable.ListBuffer ()
92
104
@ volatile var open : Boolean = true
@@ -109,20 +121,24 @@ class ClusteredBeamTest extends FunSuite with CuratorRequiringSuite with BeforeA
109
121
def close () = {
110
122
beam.close()
111
123
}
124
+
125
+ def getInterval () = None
112
126
}
113
127
114
- class TestingBeam (val timestamp : DateTime , val partition : Int , val uuid : String = UUID .randomUUID().toString)
128
+ class TestingBeam (val interval : Interval , val partition : Int , val uuid : String = UUID .randomUUID().toString)
115
129
extends Beam [SimpleEvent ]
116
130
{
117
131
_lock.synchronized {
118
132
_beams += this
119
133
}
120
134
135
+ def getInterval () = Some (interval)
136
+
121
137
def propagate (_events : Seq [SimpleEvent ]) = _lock.synchronized {
122
138
if (_events.contains(events(" defunct" ))) {
123
139
Future .exception(new DefunctBeamException (" Defunct" ))
124
140
} else {
125
- val buffer = _buffers.getOrElseUpdate(uuid, new EventBuffer (timestamp , partition))
141
+ val buffer = _buffers.getOrElseUpdate(uuid, new EventBuffer (interval , partition))
126
142
buffer.open = true
127
143
buffer.buffer ++= _events
128
144
Future .value(_events.size)
@@ -131,35 +147,35 @@ class ClusteredBeamTest extends FunSuite with CuratorRequiringSuite with BeforeA
131
147
132
148
def close () = _lock.synchronized {
133
149
_beams -= this
134
- val buffer = _buffers.getOrElseUpdate(uuid, new EventBuffer (timestamp , partition))
150
+ val buffer = _buffers.getOrElseUpdate(uuid, new EventBuffer (interval , partition))
135
151
buffer.open = false
136
152
Future .Done
137
153
}
138
154
139
155
def toDict = Dict (
140
- " timestamp " -> timestamp .toString() ,
156
+ " interval " -> interval .toString,
141
157
" partition" -> partition,
142
158
" uuid" -> uuid
143
159
)
144
160
}
145
161
146
162
class TestingBeamMaker extends BeamMaker [SimpleEvent , TestingBeam ]
147
163
{
148
- def newBeam (interval : Interval , partition : Int ) = new TestingBeam (interval.start , partition)
164
+ def newBeam (interval : Interval , partition : Int ) = new TestingBeam (interval, partition)
149
165
150
166
def toDict (beam : TestingBeam ) = {
151
167
Dict (
152
- " timestamp " -> beam.timestamp .toString() ,
168
+ " interval " -> beam.interval .toString,
153
169
" partition" -> beam.partition,
154
170
" uuid" -> beam.uuid
155
171
)
156
172
}
157
173
158
174
def fromDict (d : Dict ) = {
159
- val timestamp = new DateTime (d(" timestamp " ))
175
+ val interval = new Interval (d(" interval " ))
160
176
val partition = int(d(" partition" ))
161
177
val uuid = str(d(" uuid" ))
162
- new TestingBeam (timestamp , partition, uuid)
178
+ new TestingBeam (interval , partition, uuid)
163
179
}
164
180
}
165
181
@@ -353,6 +369,72 @@ class ClusteredBeamTest extends FunSuite with CuratorRequiringSuite with BeforeA
353
369
}
354
370
}
355
371
372
+ test(" IncreaseGranularity" ) {
373
+ withLocalCurator {
374
+ curator =>
375
+ val oldTuning = defaultTuning.copy(segmentGranularity = Granularity .MINUTE , windowPeriod = 1 .minute)
376
+ val newTuning = oldTuning.copy(segmentGranularity = Granularity .FIVE_MINUTE )
377
+
378
+ val beamsA = newBeams(curator, oldTuning)
379
+ beamsA.timekeeper.now = start
380
+ beamsA.blockagate(Seq (" i" ) map events)
381
+ beamsA.blockagate(Seq (" i" ) map events)
382
+ beamsA.timekeeper.now = start + 1 .minute
383
+ beamsA.blockagate(Seq (" j" ) map events)
384
+ beamsA.blockagate(Seq (" j" ) map events)
385
+
386
+ val beamsB = newBeams(curator, newTuning)
387
+ beamsB.timekeeper.now = start + 2 .minute
388
+ beamsB.blockagate(Seq (" k" ) map events)
389
+ beamsB.blockagate(Seq (" k" ) map events)
390
+ beamsB.blockagate(Seq (" l" ) map events)
391
+ beamsB.blockagate(Seq (" l" ) map events)
392
+ beamsB.blockagate(Seq (" m" ) map events)
393
+ beamsB.blockagate(Seq (" m" ) map events)
394
+ beamsB.blockagate(Seq (" n" ) map events)
395
+ beamsB.blockagate(Seq (" n" ) map events)
396
+
397
+ Await .result(beamsA.close())
398
+
399
+ assert(buffersWithInterval === Set (
400
+ (new Interval (" 2012-01-01T01:05Z/2012-01-01T01:06Z" , ISOChronology .getInstanceUTC), 0 , false , Seq (" i" ) map events),
401
+ (new Interval (" 2012-01-01T01:05Z/2012-01-01T01:06Z" , ISOChronology .getInstanceUTC), 1 , false , Seq (" i" ) map events),
402
+ // "j" and "l" are in same partition as diff beams were used to propagate them
403
+ (new Interval (" 2012-01-01T01:06Z/2012-01-01T01:07Z" , ISOChronology .getInstanceUTC), 0 , false , Seq (" j" , " l" ) map events),
404
+ (new Interval (" 2012-01-01T01:06Z/2012-01-01T01:07Z" , ISOChronology .getInstanceUTC), 1 , false , Seq (" j" , " l" ) map events),
405
+ (new Interval (" 2012-01-01T01:07Z/2012-01-01T01:10Z" , ISOChronology .getInstanceUTC), 0 , true , Seq (" k" , " n" ) map events),
406
+ (new Interval (" 2012-01-01T01:07Z/2012-01-01T01:10Z" , ISOChronology .getInstanceUTC), 1 , true , Seq (" k" , " n" ) map events)
407
+ ))
408
+ }
409
+ }
410
+
411
+ test(" DecreaseGranularity" ) {
412
+ withLocalCurator {
413
+ curator =>
414
+ val oldTuning = defaultTuning.copy(segmentGranularity = Granularity .FIVE_MINUTE )
415
+ val newTuning = oldTuning.copy(segmentGranularity = Granularity .MINUTE )
416
+
417
+ val beamsA = newBeams(curator, oldTuning)
418
+ beamsA.timekeeper.now = start
419
+ beamsA.blockagate(Seq (" i" ) map events)
420
+
421
+ val beamsB = newBeams(curator, newTuning)
422
+ beamsB.timekeeper.now = start + 4 .minute
423
+ beamsB.blockagate(Seq (" j" ) map events)
424
+ beamsB.blockagate(Seq (" n" ) map events)
425
+ beamsB.blockagate(Seq (" o" ) map events)
426
+ beamsB.blockagate(Seq (" o" ) map events)
427
+ Await .result(beamsB.close())
428
+
429
+ assert(buffersWithInterval === Set (
430
+ (new Interval (" 2012-01-01T01:05Z/2012-01-01T01:10Z" , ISOChronology .getInstanceUTC), 0 , false , Seq (" i" , " j" ) map events),
431
+ (new Interval (" 2012-01-01T01:05Z/2012-01-01T01:10Z" , ISOChronology .getInstanceUTC), 1 , false , Seq (" n" ) map events),
432
+ (new Interval (" 2012-01-01T01:10Z/2012-01-01T01:11Z" , ISOChronology .getInstanceUTC), 0 , false , Seq (" o" ) map events),
433
+ (new Interval (" 2012-01-01T01:10Z/2012-01-01T01:11Z" , ISOChronology .getInstanceUTC), 1 , false , Seq (" o" ) map events)
434
+ ))
435
+ }
436
+ }
437
+
356
438
test(" DefunctBeam" ) {
357
439
withLocalCurator {
358
440
curator =>
@@ -385,10 +467,10 @@ class ClusteredBeamTest extends FunSuite with CuratorRequiringSuite with BeforeA
385
467
))
386
468
val desired = List (" 2012-01-01T00Z" , " 2012-01-01T00Z" , " 2012-01-01T01Z" , " 2012-01-01T01Z" ).map(new DateTime (_))
387
469
val startTime = System .currentTimeMillis()
388
- while (System .currentTimeMillis() < startTime + 2000 && beamsList.map(_.timestamp ).sortBy(_.millis) != desired) {
470
+ while (System .currentTimeMillis() < startTime + 2000 && beamsList.map(_.interval.start ).sortBy(_.millis) != desired) {
389
471
Thread .sleep(100 )
390
472
}
391
- assert(beamsList.map(_.timestamp ).sortBy(_.millis) === desired)
473
+ assert(beamsList.map(_.interval.start ).sortBy(_.millis) === desired)
392
474
}
393
475
}
394
476
0 commit comments