This is an automated email from the ASF dual-hosted git repository.

dongjoon-hyun pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/spark-connect-swift.git


The following commit(s) were added to refs/heads/main by this push:
     new dac41be  [SPARK-60060] Make StreamingQueryStatus and 
StreamingQueryException properties public
dac41be is described below

commit dac41bef8197b6869e46ed89b968b02040359eae
Author: Dongjoon Hyun <[email protected]>
AuthorDate: Wed Oct 7 16:13:27 2026 -0700

    [SPARK-60060] Make StreamingQueryStatus and StreamingQueryException 
properties public
    
    ### What changes were proposed in this pull request?
    
    This PR aims to make the stored properties of `StreamingQueryStatus` 
(`statusMessage`, `isDataAvailable`, `isTriggerActive`, `isActive`) and 
`StreamingQueryException` (`exceptionMessage`, `errorClass`, `stackTrace`) 
`public`, with brief doc comments.
    
    ### Why are the changes needed?
    
    `StreamingQueryStatus` and `StreamingQueryException` are `public` structs 
returned by the public APIs `StreamingQuery.status()` and 
`StreamingQuery.exception()`, but their properties were `internal`. As a 
result, applications outside the `SparkConnect` module could not read any of 
the returned fields. For example, the following code failed to compile.
    
    ```swift
    let status = try await query.status()
    print(status.isActive)  // error: 'isActive' is inaccessible due to 
'internal' protection level
    ```
    
    This aligns with PySpark, where `StreamingQuery.status` and 
`StreamingQuery.exception()` expose this information to users.
    
    ### Does this PR introduce _any_ user-facing change?
    
    Yes. Users can now read the fields of `StreamingQueryStatus` and 
`StreamingQueryException`. This is an additive API change only.
    
    ### How was this patch tested?
    
    Pass the CIs with the newly added `StreamingQueryTests.status` test case.
    
    In addition, I manually verified that an out-of-module Swift package 
depending on `SparkConnect` fails to compile before this PR and compiles after 
this PR when it accesses these properties.
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    Generated-by: Claude Opus 5.5
    
    Closes #587 from dongjoon-hyun/SPARK-60060.
    
    Authored-by: Dongjoon Hyun <[email protected]>
    Signed-off-by: Dongjoon Hyun <[email protected]>
---
 Sources/SparkConnect/StreamingQuery.swift         | 21 ++++++++-----
 Tests/SparkConnectTests/StreamingQueryTests.swift | 37 +++++++++++++++++++++++
 2 files changed, 51 insertions(+), 7 deletions(-)

diff --git a/Sources/SparkConnect/StreamingQuery.swift 
b/Sources/SparkConnect/StreamingQuery.swift
index f7cb5d8..dd833e1 100644
--- a/Sources/SparkConnect/StreamingQuery.swift
+++ b/Sources/SparkConnect/StreamingQuery.swift
@@ -23,16 +23,23 @@ import Foundation
 #endif
 
 public struct StreamingQueryException: Sendable {
-  let exceptionMessage: String
-  let errorClass: String
-  let stackTrace: String
+  /// The exception message as a string.
+  public let exceptionMessage: String
+  /// The error class of the exception.
+  public let errorClass: String
+  /// The stack trace of the exception.
+  public let stackTrace: String
 }
 
 public struct StreamingQueryStatus: Sendable {
-  let statusMessage: String
-  let isDataAvailable: Bool
-  let isTriggerActive: Bool
-  let isActive: Bool
+  /// A human-readable description of what the query is currently doing.
+  public let statusMessage: String
+  /// Whether there is new data available to be processed.
+  public let isDataAvailable: Bool
+  /// Whether the trigger is actively firing.
+  public let isTriggerActive: Bool
+  /// Whether the query is actively running.
+  public let isActive: Bool
 }
 
 /// A handle to a query that is executing continuously in the background as 
new data arrives.
diff --git a/Tests/SparkConnectTests/StreamingQueryTests.swift 
b/Tests/SparkConnectTests/StreamingQueryTests.swift
index 69be862..0d37d4b 100644
--- a/Tests/SparkConnectTests/StreamingQueryTests.swift
+++ b/Tests/SparkConnectTests/StreamingQueryTests.swift
@@ -93,6 +93,43 @@ struct StreamingQueryTests {
     await spark.stop()
   }
 
+  @Test
+  func status() async throws {
+    let spark = try await SparkSession.builder.getOrCreate()
+
+    // Prepare directories
+    let input = "/tmp/input-" + UUID().uuidString
+    let checkpoint = "/tmp/checkpoint-" + UUID().uuidString
+    let output = "/tmp/output-" + UUID().uuidString
+    try await spark.range(2025).write.orc(input)
+
+    // Start a streaming query
+    let query =
+      try await spark
+      .readStream
+      .schema("id LONG")
+      .orc(input)
+      .writeStream
+      .option("checkpointLocation", checkpoint)
+      .outputMode("append")
+      .format("orc")
+      .trigger(Trigger.ProcessingTime(1000))
+      .start(output)
+
+    let status = try await query.status()
+    #expect(status.isActive)
+    #expect(status.statusMessage.isEmpty == false)
+
+    try await query.stop()
+    let stoppedStatus = try await query.status()
+    #expect(stoppedStatus.isActive == false)
+    #expect(stoppedStatus.isDataAvailable == false)
+    #expect(stoppedStatus.isTriggerActive == false)
+    #expect(stoppedStatus.statusMessage == "Stopped")
+
+    await spark.stop()
+  }
+
   @Test
   func progress() async throws {
     let spark = try await SparkSession.builder.getOrCreate()


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to