@@ -44,6 +44,7 @@ import org.apache.curator.framework.CuratorFramework
4444import org .joda .time .DateTimeZone
4545import org .joda .time .DateTime
4646import org .joda .time .Interval
47+ import org .joda .time .chrono .ISOChronology
4748import org .scala_tools .time .Implicits ._
4849import org .scalatest .BeforeAndAfter
4950import org .scalatest .FunSuite
@@ -68,7 +69,14 @@ class ClusteredBeamTest extends FunSuite with CuratorRequiringSuite with BeforeA
6869 SimpleEvent (new DateTime (" 2012-01-01T01:10Z" ), Map (" foo" -> " e" )),
6970 SimpleEvent (new DateTime (" 2012-01-01T01:20Z" ), Map (" foo" -> " f" )),
7071 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" ))
7280 ) map {
7381 x => x.fields(" foo" ) -> x
7482 }).toMap
@@ -79,14 +87,18 @@ class ClusteredBeamTest extends FunSuite with CuratorRequiringSuite with BeforeA
7987 val localZone = new DateTime ().getZone
8088
8189 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
8395 }
8496
8597 def beamsList = _lock.synchronized {
8698 _beams.toList
8799 }
88100
89- class EventBuffer (val timestamp : DateTime , val partition : Int )
101+ class EventBuffer (val interval : Interval , val partition : Int )
90102 {
91103 val buffer : mutable.Buffer [SimpleEvent ] = mutable.ListBuffer ()
92104 @ volatile var open : Boolean = true
@@ -113,20 +125,20 @@ class ClusteredBeamTest extends FunSuite with CuratorRequiringSuite with BeforeA
113125 def getInterval () = None
114126 }
115127
116- 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)
117129 extends Beam [SimpleEvent ]
118130 {
119131 _lock.synchronized {
120132 _beams += this
121133 }
122134
123- def getInterval () = None
135+ def getInterval () = Some (interval)
124136
125137 def propagate (_events : Seq [SimpleEvent ]) = _lock.synchronized {
126138 if (_events.contains(events(" defunct" ))) {
127139 Future .exception(new DefunctBeamException (" Defunct" ))
128140 } else {
129- val buffer = _buffers.getOrElseUpdate(uuid, new EventBuffer (timestamp , partition))
141+ val buffer = _buffers.getOrElseUpdate(uuid, new EventBuffer (interval , partition))
130142 buffer.open = true
131143 buffer.buffer ++= _events
132144 Future .value(_events.size)
@@ -135,35 +147,35 @@ class ClusteredBeamTest extends FunSuite with CuratorRequiringSuite with BeforeA
135147
136148 def close () = _lock.synchronized {
137149 _beams -= this
138- val buffer = _buffers.getOrElseUpdate(uuid, new EventBuffer (timestamp , partition))
150+ val buffer = _buffers.getOrElseUpdate(uuid, new EventBuffer (interval , partition))
139151 buffer.open = false
140152 Future .Done
141153 }
142154
143155 def toDict = Dict (
144- " timestamp " -> timestamp .toString() ,
156+ " interval " -> interval .toString,
145157 " partition" -> partition,
146158 " uuid" -> uuid
147159 )
148160 }
149161
150162 class TestingBeamMaker extends BeamMaker [SimpleEvent , TestingBeam ]
151163 {
152- def newBeam (interval : Interval , partition : Int ) = new TestingBeam (interval.start , partition)
164+ def newBeam (interval : Interval , partition : Int ) = new TestingBeam (interval, partition)
153165
154166 def toDict (beam : TestingBeam ) = {
155167 Dict (
156- " timestamp " -> beam.timestamp .toString() ,
168+ " interval " -> beam.interval .toString,
157169 " partition" -> beam.partition,
158170 " uuid" -> beam.uuid
159171 )
160172 }
161173
162174 def fromDict (d : Dict ) = {
163- val timestamp = new DateTime (d(" timestamp " ))
175+ val interval = new Interval (d(" interval " ))
164176 val partition = int(d(" partition" ))
165177 val uuid = str(d(" uuid" ))
166- new TestingBeam (timestamp , partition, uuid)
178+ new TestingBeam (interval , partition, uuid)
167179 }
168180 }
169181
@@ -357,6 +369,72 @@ class ClusteredBeamTest extends FunSuite with CuratorRequiringSuite with BeforeA
357369 }
358370 }
359371
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+
360438 test(" DefunctBeam" ) {
361439 withLocalCurator {
362440 curator =>
@@ -389,10 +467,10 @@ class ClusteredBeamTest extends FunSuite with CuratorRequiringSuite with BeforeA
389467 ))
390468 val desired = List (" 2012-01-01T00Z" , " 2012-01-01T00Z" , " 2012-01-01T01Z" , " 2012-01-01T01Z" ).map(new DateTime (_))
391469 val startTime = System .currentTimeMillis()
392- while (System .currentTimeMillis() < startTime + 2000 && beamsList.map(_.timestamp ).sortBy(_.millis) != desired) {
470+ while (System .currentTimeMillis() < startTime + 2000 && beamsList.map(_.interval.start ).sortBy(_.millis) != desired) {
393471 Thread .sleep(100 )
394472 }
395- assert(beamsList.map(_.timestamp ).sortBy(_.millis) === desired)
473+ assert(beamsList.map(_.interval.start ).sortBy(_.millis) === desired)
396474 }
397475 }
398476
0 commit comments