Skip to content

Commit 4f7ee7f

Browse files
committed
Add ContinuousQueryInfo to make ContinuousQueryListener events serializable
1 parent 0f61d6e commit 4f7ee7f

3 files changed

Lines changed: 38 additions & 29 deletions

File tree

sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/StreamExecution.scala

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import org.apache.spark.sql.catalyst.expressions.{Attribute, AttributeMap}
3434
import org.apache.spark.sql.catalyst.plans.logical.{LocalRelation, LogicalPlan}
3535
import org.apache.spark.sql.catalyst.util._
3636
import org.apache.spark.sql.execution.QueryExecution
37-
import org.apache.spark.sql.util.ContinuousQueryListener
37+
import org.apache.spark.sql.util.{ContinuousQueryInfo, ContinuousQueryListener}
3838
import org.apache.spark.sql.util.ContinuousQueryListener._
3939
import org.apache.spark.util.{Clock, UninterruptibleThread, Utils}
4040

@@ -167,7 +167,7 @@ class StreamExecution(
167167
// Mark ACTIVE and then post the event. QueryStarted event is synchronously sent to listeners,
168168
// so must mark this as ACTIVE first.
169169
state = ACTIVE
170-
postEvent(new QueryStarted(this)) // Assumption: Does not throw exception.
170+
postEvent(new QueryStarted(this.toInfo)) // Assumption: Does not throw exception.
171171

172172
// Unblock starting thread
173173
startLatch.countDown()
@@ -206,7 +206,7 @@ class StreamExecution(
206206
} finally {
207207
state = TERMINATED
208208
sparkSession.streams.notifyQueryTermination(StreamExecution.this)
209-
postEvent(new QueryTerminated(this))
209+
postEvent(new QueryTerminated(this.toInfo))
210210
terminationLatch.countDown()
211211
}
212212
}
@@ -374,7 +374,7 @@ class StreamExecution(
374374
logInfo(s"Completed up to $availableOffsets in ${batchTime}ms")
375375
// Update committed offsets.
376376
committedOffsets ++= availableOffsets
377-
postEvent(new QueryProgress(this))
377+
postEvent(new QueryProgress(this.toInfo))
378378
}
379379

380380
private def postEvent(event: ContinuousQueryListener.Event) {
@@ -484,6 +484,15 @@ class StreamExecution(
484484
""".stripMargin
485485
}
486486

487+
private def toInfo: ContinuousQueryInfo = {
488+
ContinuousQueryInfo(
489+
this.name,
490+
this.isActive,
491+
this.sourceStatuses,
492+
this.sinkStatus,
493+
this.exception)
494+
}
495+
487496
trait State
488497
case object INITIALIZED extends State
489498
case object ACTIVE extends State

sql/core/src/main/scala/org/apache/spark/sql/util/ContinuousQueryListener.scala

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
package org.apache.spark.sql.util
1919

2020
import org.apache.spark.annotation.Experimental
21-
import org.apache.spark.sql.ContinuousQuery
21+
import org.apache.spark.sql._
2222
import org.apache.spark.sql.util.ContinuousQueryListener._
2323

2424
/**
@@ -65,11 +65,23 @@ object ContinuousQueryListener {
6565
trait Event
6666

6767
/** Event representing the start of a query */
68-
class QueryStarted private[sql](val query: ContinuousQuery) extends Event
68+
class QueryStarted private[sql](val queryInfo: ContinuousQueryInfo) extends Event
6969

7070
/** Event representing any progress updates in a query */
71-
class QueryProgress private[sql](val query: ContinuousQuery) extends Event
71+
class QueryProgress private[sql](val queryInfo: ContinuousQueryInfo) extends Event
7272

7373
/** Event representing that termination of a query */
74-
class QueryTerminated private[sql](val query: ContinuousQuery) extends Event
74+
class QueryTerminated private[sql](val queryInfo: ContinuousQueryInfo) extends Event
7575
}
76+
77+
/**
78+
* :: Experimental ::
79+
* Companion object of [[ContinuousQueryListener]] that defines the listener events.
80+
*/
81+
@Experimental
82+
case class ContinuousQueryInfo(
83+
name: String,
84+
isActive: Boolean,
85+
sourceStatuses: Seq[SourceStatus],
86+
sinkStatus: SinkStatus,
87+
exception: Option[ContinuousQueryException])

sql/core/src/test/scala/org/apache/spark/sql/util/ContinuousQueryListenerSuite.scala

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class ContinuousQueryListenerSuite extends StreamTest with SharedSQLContext with
5252
Assert("Incorrect query status in onQueryStarted") {
5353
val status = listener.startStatus
5454
assert(status != null)
55-
assert(status.active == true)
55+
assert(status.isActive == true)
5656
assert(status.sourceStatuses.size === 1)
5757
assert(status.sourceStatuses(0).description.contains("Memory"))
5858

@@ -74,7 +74,7 @@ class ContinuousQueryListenerSuite extends StreamTest with SharedSQLContext with
7474
assert(listener.progressStatuses.size === 1)
7575
val status = listener.progressStatuses.peek()
7676
assert(status != null)
77-
assert(status.active == true)
77+
assert(status.isActive == true)
7878
assert(status.sourceStatuses(0).offset === Some(LongOffset(0)))
7979
assert(status.sinkStatus.offset === CompositeOffset.fill(LongOffset(0)))
8080

@@ -88,7 +88,7 @@ class ContinuousQueryListenerSuite extends StreamTest with SharedSQLContext with
8888
val status = listener.terminationStatus
8989
assert(status != null)
9090

91-
assert(status.active === false) // must be inactive by the time onQueryTerm is called
91+
assert(status.isActive === false) // must be inactive by the time onQueryTerm is called
9292
assert(status.sourceStatuses(0).offset === Some(LongOffset(0)))
9393
assert(status.sinkStatus.offset === CompositeOffset.fill(LongOffset(0)))
9494
}
@@ -165,9 +165,9 @@ class ContinuousQueryListenerSuite extends StreamTest with SharedSQLContext with
165165
// to catch errors in the async listener events
166166
@volatile private var asyncTestWaiter = new Waiter
167167

168-
@volatile var startStatus: QueryStatus = null
169-
@volatile var terminationStatus: QueryStatus = null
170-
val progressStatuses = new ConcurrentLinkedQueue[QueryStatus]
168+
@volatile var startStatus: ContinuousQueryInfo = null
169+
@volatile var terminationStatus: ContinuousQueryInfo = null
170+
val progressStatuses = new ConcurrentLinkedQueue[ContinuousQueryInfo]
171171

172172
def reset(): Unit = {
173173
startStatus = null
@@ -183,35 +183,23 @@ class ContinuousQueryListenerSuite extends StreamTest with SharedSQLContext with
183183

184184
override def onQueryStarted(queryStarted: QueryStarted): Unit = {
185185
asyncTestWaiter {
186-
startStatus = QueryStatus(queryStarted.query)
186+
startStatus = queryStarted.queryInfo
187187
}
188188
}
189189

190190
override def onQueryProgress(queryProgress: QueryProgress): Unit = {
191191
asyncTestWaiter {
192192
assert(startStatus != null, "onQueryProgress called before onQueryStarted")
193-
progressStatuses.add(QueryStatus(queryProgress.query))
193+
progressStatuses.add(queryProgress.queryInfo)
194194
}
195195
}
196196

197197
override def onQueryTerminated(queryTerminated: QueryTerminated): Unit = {
198198
asyncTestWaiter {
199199
assert(startStatus != null, "onQueryTerminated called before onQueryStarted")
200-
terminationStatus = QueryStatus(queryTerminated.query)
200+
terminationStatus = queryTerminated.queryInfo
201201
}
202202
asyncTestWaiter.dismiss()
203203
}
204204
}
205-
206-
case class QueryStatus(
207-
active: Boolean,
208-
exception: Option[Exception],
209-
sourceStatuses: Array[SourceStatus],
210-
sinkStatus: SinkStatus)
211-
212-
object QueryStatus {
213-
def apply(query: ContinuousQuery): QueryStatus = {
214-
QueryStatus(query.isActive, query.exception, query.sourceStatuses, query.sinkStatus)
215-
}
216-
}
217205
}

0 commit comments

Comments
 (0)