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

ruifengz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/master by this push:
     new a3a8d1ca668a [SPARK-50715][PYTHON][CONNECT] `SparkSession.Builder` 
sets the configs in batch
a3a8d1ca668a is described below

commit a3a8d1ca668aae61f672c84a8873960edb8ab37b
Author: Ruifeng Zheng <[email protected]>
AuthorDate: Fri Jan 3 12:40:07 2025 +0800

    [SPARK-50715][PYTHON][CONNECT] `SparkSession.Builder` sets the configs in 
batch
    
    ### What changes were proposed in this pull request?
    `SparkSession.Builder` sets the configs in batch
    
    ### Why are the changes needed?
    I notice that there are practice workflows with 500+ configs, existing 
implementation always set the configs one by one, and thus cause 500+ `Config` 
RPCs.
    
    ### Does this PR introduce _any_ user-facing change?
    No, internal change
    
    ### How was this patch tested?
    Existing CI
    
    ### Was this patch authored or co-authored using generative AI tooling?
    No
    
    Closes #49346 from zhengruifeng/py_connect_set_all.
    
    Authored-by: Ruifeng Zheng <[email protected]>
    Signed-off-by: Ruifeng Zheng <[email protected]>
---
 python/pyspark/sql/connect/conf.py                 |  14 ++
 python/pyspark/sql/connect/proto/base_pb2.py       | 162 ++++++++++-----------
 python/pyspark/sql/connect/proto/base_pb2.pyi      |  17 ++-
 python/pyspark/sql/connect/session.py              |  40 ++---
 .../src/main/protobuf/spark/connect/base.proto     |   3 +
 .../service/SparkConnectConfigHandler.scala        |  14 +-
 6 files changed, 142 insertions(+), 108 deletions(-)

diff --git a/python/pyspark/sql/connect/conf.py 
b/python/pyspark/sql/connect/conf.py
index 1ef72ee3cfa4..84d7ad34fb36 100644
--- a/python/pyspark/sql/connect/conf.py
+++ b/python/pyspark/sql/connect/conf.py
@@ -49,6 +49,20 @@ class RuntimeConf:
 
     set.__doc__ = PySparkRuntimeConfig.set.__doc__
 
+    def _set_all(self, configs: Dict[str, Union[str, int, bool]], silent: 
bool) -> None:
+        conf_list = []
+        for key, value in configs.items():
+            if isinstance(value, bool):
+                value = "true" if value else "false"
+            elif isinstance(value, int):
+                value = str(value)
+            conf_list.append(proto.KeyValue(key=key, value=value))
+        op_set = proto.ConfigRequest.Set(pairs=conf_list, silent=silent)
+        operation = proto.ConfigRequest.Operation(set=op_set)
+        result = self._client.config(operation)
+        for warn in result.warnings:
+            warnings.warn(warn)
+
     def get(
         self, key: str, default: Union[Optional[str], _NoValueType] = _NoValue
     ) -> Optional[str]:
diff --git a/python/pyspark/sql/connect/proto/base_pb2.py 
b/python/pyspark/sql/connect/proto/base_pb2.py
index 6e946a5bd4ae..64c549ffe956 100644
--- a/python/pyspark/sql/connect/proto/base_pb2.py
+++ b/python/pyspark/sql/connect/proto/base_pb2.py
@@ -43,7 +43,7 @@ from pyspark.sql.connect.proto import types_pb2 as 
spark_dot_connect_dot_types__
 
 
 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(
-    
b'\n\x18spark/connect/base.proto\x12\rspark.connect\x1a\x19google/protobuf/any.proto\x1a\x1cspark/connect/commands.proto\x1a\x1aspark/connect/common.proto\x1a\x1fspark/connect/expressions.proto\x1a\x1dspark/connect/relations.proto\x1a\x19spark/connect/types.proto"t\n\x04Plan\x12-\n\x04root\x18\x01
 
\x01(\x0b\x32\x17.spark.connect.RelationH\x00R\x04root\x12\x32\n\x07\x63ommand\x18\x02
 
\x01(\x0b\x32\x16.spark.connect.CommandH\x00R\x07\x63ommandB\t\n\x07op_type"z\n\x0bUserContext\x12\x17
 [...]
+    
b'\n\x18spark/connect/base.proto\x12\rspark.connect\x1a\x19google/protobuf/any.proto\x1a\x1cspark/connect/commands.proto\x1a\x1aspark/connect/common.proto\x1a\x1fspark/connect/expressions.proto\x1a\x1dspark/connect/relations.proto\x1a\x19spark/connect/types.proto"t\n\x04Plan\x12-\n\x04root\x18\x01
 
\x01(\x0b\x32\x17.spark.connect.RelationH\x00R\x04root\x12\x32\n\x07\x63ommand\x18\x02
 
\x01(\x0b\x32\x16.spark.connect.CommandH\x00R\x07\x63ommandB\t\n\x07op_type"z\n\x0bUserContext\x12\x17
 [...]
 )
 
 _globals = globals()
@@ -167,91 +167,91 @@ if not _descriptor._USE_C_DESCRIPTORS:
     _globals["_KEYVALUE"]._serialized_start = 8609
     _globals["_KEYVALUE"]._serialized_end = 8674
     _globals["_CONFIGREQUEST"]._serialized_start = 8677
-    _globals["_CONFIGREQUEST"]._serialized_end = 9836
+    _globals["_CONFIGREQUEST"]._serialized_end = 9876
     _globals["_CONFIGREQUEST_OPERATION"]._serialized_start = 8985
     _globals["_CONFIGREQUEST_OPERATION"]._serialized_end = 9483
     _globals["_CONFIGREQUEST_SET"]._serialized_start = 9485
-    _globals["_CONFIGREQUEST_SET"]._serialized_end = 9537
-    _globals["_CONFIGREQUEST_GET"]._serialized_start = 9539
-    _globals["_CONFIGREQUEST_GET"]._serialized_end = 9564
-    _globals["_CONFIGREQUEST_GETWITHDEFAULT"]._serialized_start = 9566
-    _globals["_CONFIGREQUEST_GETWITHDEFAULT"]._serialized_end = 9629
-    _globals["_CONFIGREQUEST_GETOPTION"]._serialized_start = 9631
-    _globals["_CONFIGREQUEST_GETOPTION"]._serialized_end = 9662
-    _globals["_CONFIGREQUEST_GETALL"]._serialized_start = 9664
-    _globals["_CONFIGREQUEST_GETALL"]._serialized_end = 9712
-    _globals["_CONFIGREQUEST_UNSET"]._serialized_start = 9714
-    _globals["_CONFIGREQUEST_UNSET"]._serialized_end = 9741
-    _globals["_CONFIGREQUEST_ISMODIFIABLE"]._serialized_start = 9743
-    _globals["_CONFIGREQUEST_ISMODIFIABLE"]._serialized_end = 9777
-    _globals["_CONFIGRESPONSE"]._serialized_start = 9839
-    _globals["_CONFIGRESPONSE"]._serialized_end = 10014
-    _globals["_ADDARTIFACTSREQUEST"]._serialized_start = 10017
-    _globals["_ADDARTIFACTSREQUEST"]._serialized_end = 11019
-    _globals["_ADDARTIFACTSREQUEST_ARTIFACTCHUNK"]._serialized_start = 10492
-    _globals["_ADDARTIFACTSREQUEST_ARTIFACTCHUNK"]._serialized_end = 10545
-    _globals["_ADDARTIFACTSREQUEST_SINGLECHUNKARTIFACT"]._serialized_start = 
10547
-    _globals["_ADDARTIFACTSREQUEST_SINGLECHUNKARTIFACT"]._serialized_end = 
10658
-    _globals["_ADDARTIFACTSREQUEST_BATCH"]._serialized_start = 10660
-    _globals["_ADDARTIFACTSREQUEST_BATCH"]._serialized_end = 10753
-    _globals["_ADDARTIFACTSREQUEST_BEGINCHUNKEDARTIFACT"]._serialized_start = 
10756
-    _globals["_ADDARTIFACTSREQUEST_BEGINCHUNKEDARTIFACT"]._serialized_end = 
10949
-    _globals["_ADDARTIFACTSRESPONSE"]._serialized_start = 11022
-    _globals["_ADDARTIFACTSRESPONSE"]._serialized_end = 11294
-    _globals["_ADDARTIFACTSRESPONSE_ARTIFACTSUMMARY"]._serialized_start = 11213
-    _globals["_ADDARTIFACTSRESPONSE_ARTIFACTSUMMARY"]._serialized_end = 11294
-    _globals["_ARTIFACTSTATUSESREQUEST"]._serialized_start = 11297
-    _globals["_ARTIFACTSTATUSESREQUEST"]._serialized_end = 11623
-    _globals["_ARTIFACTSTATUSESRESPONSE"]._serialized_start = 11626
-    _globals["_ARTIFACTSTATUSESRESPONSE"]._serialized_end = 11978
-    _globals["_ARTIFACTSTATUSESRESPONSE_STATUSESENTRY"]._serialized_start = 
11821
-    _globals["_ARTIFACTSTATUSESRESPONSE_STATUSESENTRY"]._serialized_end = 11936
-    _globals["_ARTIFACTSTATUSESRESPONSE_ARTIFACTSTATUS"]._serialized_start = 
11938
-    _globals["_ARTIFACTSTATUSESRESPONSE_ARTIFACTSTATUS"]._serialized_end = 
11978
-    _globals["_INTERRUPTREQUEST"]._serialized_start = 11981
-    _globals["_INTERRUPTREQUEST"]._serialized_end = 12584
-    _globals["_INTERRUPTREQUEST_INTERRUPTTYPE"]._serialized_start = 12384
-    _globals["_INTERRUPTREQUEST_INTERRUPTTYPE"]._serialized_end = 12512
-    _globals["_INTERRUPTRESPONSE"]._serialized_start = 12587
-    _globals["_INTERRUPTRESPONSE"]._serialized_end = 12731
-    _globals["_REATTACHOPTIONS"]._serialized_start = 12733
-    _globals["_REATTACHOPTIONS"]._serialized_end = 12786
-    _globals["_REATTACHEXECUTEREQUEST"]._serialized_start = 12789
-    _globals["_REATTACHEXECUTEREQUEST"]._serialized_end = 13195
-    _globals["_RELEASEEXECUTEREQUEST"]._serialized_start = 13198
-    _globals["_RELEASEEXECUTEREQUEST"]._serialized_end = 13783
-    _globals["_RELEASEEXECUTEREQUEST_RELEASEALL"]._serialized_start = 13652
-    _globals["_RELEASEEXECUTEREQUEST_RELEASEALL"]._serialized_end = 13664
-    _globals["_RELEASEEXECUTEREQUEST_RELEASEUNTIL"]._serialized_start = 13666
-    _globals["_RELEASEEXECUTEREQUEST_RELEASEUNTIL"]._serialized_end = 13713
-    _globals["_RELEASEEXECUTERESPONSE"]._serialized_start = 13786
-    _globals["_RELEASEEXECUTERESPONSE"]._serialized_end = 13951
-    _globals["_RELEASESESSIONREQUEST"]._serialized_start = 13954
-    _globals["_RELEASESESSIONREQUEST"]._serialized_end = 14166
-    _globals["_RELEASESESSIONRESPONSE"]._serialized_start = 14168
-    _globals["_RELEASESESSIONRESPONSE"]._serialized_end = 14276
-    _globals["_FETCHERRORDETAILSREQUEST"]._serialized_start = 14279
-    _globals["_FETCHERRORDETAILSREQUEST"]._serialized_end = 14611
-    _globals["_FETCHERRORDETAILSRESPONSE"]._serialized_start = 14614
-    _globals["_FETCHERRORDETAILSRESPONSE"]._serialized_end = 16169
-    _globals["_FETCHERRORDETAILSRESPONSE_STACKTRACEELEMENT"]._serialized_start 
= 14843
-    _globals["_FETCHERRORDETAILSRESPONSE_STACKTRACEELEMENT"]._serialized_end = 
15017
-    _globals["_FETCHERRORDETAILSRESPONSE_QUERYCONTEXT"]._serialized_start = 
15020
-    _globals["_FETCHERRORDETAILSRESPONSE_QUERYCONTEXT"]._serialized_end = 15388
-    
_globals["_FETCHERRORDETAILSRESPONSE_QUERYCONTEXT_CONTEXTTYPE"]._serialized_start
 = 15351
-    
_globals["_FETCHERRORDETAILSRESPONSE_QUERYCONTEXT_CONTEXTTYPE"]._serialized_end 
= 15388
-    _globals["_FETCHERRORDETAILSRESPONSE_SPARKTHROWABLE"]._serialized_start = 
15391
-    _globals["_FETCHERRORDETAILSRESPONSE_SPARKTHROWABLE"]._serialized_end = 
15800
+    _globals["_CONFIGREQUEST_SET"]._serialized_end = 9577
+    _globals["_CONFIGREQUEST_GET"]._serialized_start = 9579
+    _globals["_CONFIGREQUEST_GET"]._serialized_end = 9604
+    _globals["_CONFIGREQUEST_GETWITHDEFAULT"]._serialized_start = 9606
+    _globals["_CONFIGREQUEST_GETWITHDEFAULT"]._serialized_end = 9669
+    _globals["_CONFIGREQUEST_GETOPTION"]._serialized_start = 9671
+    _globals["_CONFIGREQUEST_GETOPTION"]._serialized_end = 9702
+    _globals["_CONFIGREQUEST_GETALL"]._serialized_start = 9704
+    _globals["_CONFIGREQUEST_GETALL"]._serialized_end = 9752
+    _globals["_CONFIGREQUEST_UNSET"]._serialized_start = 9754
+    _globals["_CONFIGREQUEST_UNSET"]._serialized_end = 9781
+    _globals["_CONFIGREQUEST_ISMODIFIABLE"]._serialized_start = 9783
+    _globals["_CONFIGREQUEST_ISMODIFIABLE"]._serialized_end = 9817
+    _globals["_CONFIGRESPONSE"]._serialized_start = 9879
+    _globals["_CONFIGRESPONSE"]._serialized_end = 10054
+    _globals["_ADDARTIFACTSREQUEST"]._serialized_start = 10057
+    _globals["_ADDARTIFACTSREQUEST"]._serialized_end = 11059
+    _globals["_ADDARTIFACTSREQUEST_ARTIFACTCHUNK"]._serialized_start = 10532
+    _globals["_ADDARTIFACTSREQUEST_ARTIFACTCHUNK"]._serialized_end = 10585
+    _globals["_ADDARTIFACTSREQUEST_SINGLECHUNKARTIFACT"]._serialized_start = 
10587
+    _globals["_ADDARTIFACTSREQUEST_SINGLECHUNKARTIFACT"]._serialized_end = 
10698
+    _globals["_ADDARTIFACTSREQUEST_BATCH"]._serialized_start = 10700
+    _globals["_ADDARTIFACTSREQUEST_BATCH"]._serialized_end = 10793
+    _globals["_ADDARTIFACTSREQUEST_BEGINCHUNKEDARTIFACT"]._serialized_start = 
10796
+    _globals["_ADDARTIFACTSREQUEST_BEGINCHUNKEDARTIFACT"]._serialized_end = 
10989
+    _globals["_ADDARTIFACTSRESPONSE"]._serialized_start = 11062
+    _globals["_ADDARTIFACTSRESPONSE"]._serialized_end = 11334
+    _globals["_ADDARTIFACTSRESPONSE_ARTIFACTSUMMARY"]._serialized_start = 11253
+    _globals["_ADDARTIFACTSRESPONSE_ARTIFACTSUMMARY"]._serialized_end = 11334
+    _globals["_ARTIFACTSTATUSESREQUEST"]._serialized_start = 11337
+    _globals["_ARTIFACTSTATUSESREQUEST"]._serialized_end = 11663
+    _globals["_ARTIFACTSTATUSESRESPONSE"]._serialized_start = 11666
+    _globals["_ARTIFACTSTATUSESRESPONSE"]._serialized_end = 12018
+    _globals["_ARTIFACTSTATUSESRESPONSE_STATUSESENTRY"]._serialized_start = 
11861
+    _globals["_ARTIFACTSTATUSESRESPONSE_STATUSESENTRY"]._serialized_end = 11976
+    _globals["_ARTIFACTSTATUSESRESPONSE_ARTIFACTSTATUS"]._serialized_start = 
11978
+    _globals["_ARTIFACTSTATUSESRESPONSE_ARTIFACTSTATUS"]._serialized_end = 
12018
+    _globals["_INTERRUPTREQUEST"]._serialized_start = 12021
+    _globals["_INTERRUPTREQUEST"]._serialized_end = 12624
+    _globals["_INTERRUPTREQUEST_INTERRUPTTYPE"]._serialized_start = 12424
+    _globals["_INTERRUPTREQUEST_INTERRUPTTYPE"]._serialized_end = 12552
+    _globals["_INTERRUPTRESPONSE"]._serialized_start = 12627
+    _globals["_INTERRUPTRESPONSE"]._serialized_end = 12771
+    _globals["_REATTACHOPTIONS"]._serialized_start = 12773
+    _globals["_REATTACHOPTIONS"]._serialized_end = 12826
+    _globals["_REATTACHEXECUTEREQUEST"]._serialized_start = 12829
+    _globals["_REATTACHEXECUTEREQUEST"]._serialized_end = 13235
+    _globals["_RELEASEEXECUTEREQUEST"]._serialized_start = 13238
+    _globals["_RELEASEEXECUTEREQUEST"]._serialized_end = 13823
+    _globals["_RELEASEEXECUTEREQUEST_RELEASEALL"]._serialized_start = 13692
+    _globals["_RELEASEEXECUTEREQUEST_RELEASEALL"]._serialized_end = 13704
+    _globals["_RELEASEEXECUTEREQUEST_RELEASEUNTIL"]._serialized_start = 13706
+    _globals["_RELEASEEXECUTEREQUEST_RELEASEUNTIL"]._serialized_end = 13753
+    _globals["_RELEASEEXECUTERESPONSE"]._serialized_start = 13826
+    _globals["_RELEASEEXECUTERESPONSE"]._serialized_end = 13991
+    _globals["_RELEASESESSIONREQUEST"]._serialized_start = 13994
+    _globals["_RELEASESESSIONREQUEST"]._serialized_end = 14206
+    _globals["_RELEASESESSIONRESPONSE"]._serialized_start = 14208
+    _globals["_RELEASESESSIONRESPONSE"]._serialized_end = 14316
+    _globals["_FETCHERRORDETAILSREQUEST"]._serialized_start = 14319
+    _globals["_FETCHERRORDETAILSREQUEST"]._serialized_end = 14651
+    _globals["_FETCHERRORDETAILSRESPONSE"]._serialized_start = 14654
+    _globals["_FETCHERRORDETAILSRESPONSE"]._serialized_end = 16209
+    _globals["_FETCHERRORDETAILSRESPONSE_STACKTRACEELEMENT"]._serialized_start 
= 14883
+    _globals["_FETCHERRORDETAILSRESPONSE_STACKTRACEELEMENT"]._serialized_end = 
15057
+    _globals["_FETCHERRORDETAILSRESPONSE_QUERYCONTEXT"]._serialized_start = 
15060
+    _globals["_FETCHERRORDETAILSRESPONSE_QUERYCONTEXT"]._serialized_end = 15428
+    
_globals["_FETCHERRORDETAILSRESPONSE_QUERYCONTEXT_CONTEXTTYPE"]._serialized_start
 = 15391
+    
_globals["_FETCHERRORDETAILSRESPONSE_QUERYCONTEXT_CONTEXTTYPE"]._serialized_end 
= 15428
+    _globals["_FETCHERRORDETAILSRESPONSE_SPARKTHROWABLE"]._serialized_start = 
15431
+    _globals["_FETCHERRORDETAILSRESPONSE_SPARKTHROWABLE"]._serialized_end = 
15840
     _globals[
         "_FETCHERRORDETAILSRESPONSE_SPARKTHROWABLE_MESSAGEPARAMETERSENTRY"
-    ]._serialized_start = 15702
+    ]._serialized_start = 15742
     _globals[
         "_FETCHERRORDETAILSRESPONSE_SPARKTHROWABLE_MESSAGEPARAMETERSENTRY"
-    ]._serialized_end = 15770
-    _globals["_FETCHERRORDETAILSRESPONSE_ERROR"]._serialized_start = 15803
-    _globals["_FETCHERRORDETAILSRESPONSE_ERROR"]._serialized_end = 16150
-    _globals["_CHECKPOINTCOMMANDRESULT"]._serialized_start = 16171
-    _globals["_CHECKPOINTCOMMANDRESULT"]._serialized_end = 16261
-    _globals["_SPARKCONNECTSERVICE"]._serialized_start = 16264
-    _globals["_SPARKCONNECTSERVICE"]._serialized_end = 17210
+    ]._serialized_end = 15810
+    _globals["_FETCHERRORDETAILSRESPONSE_ERROR"]._serialized_start = 15843
+    _globals["_FETCHERRORDETAILSRESPONSE_ERROR"]._serialized_end = 16190
+    _globals["_CHECKPOINTCOMMANDRESULT"]._serialized_start = 16211
+    _globals["_CHECKPOINTCOMMANDRESULT"]._serialized_end = 16301
+    _globals["_SPARKCONNECTSERVICE"]._serialized_start = 16304
+    _globals["_SPARKCONNECTSERVICE"]._serialized_end = 17250
 # @@protoc_insertion_point(module_scope)
diff --git a/python/pyspark/sql/connect/proto/base_pb2.pyi 
b/python/pyspark/sql/connect/proto/base_pb2.pyi
index fc3a7e804f27..adea62ed6b80 100644
--- a/python/pyspark/sql/connect/proto/base_pb2.pyi
+++ b/python/pyspark/sql/connect/proto/base_pb2.pyi
@@ -1921,17 +1921,32 @@ class ConfigRequest(google.protobuf.message.Message):
         DESCRIPTOR: google.protobuf.descriptor.Descriptor
 
         PAIRS_FIELD_NUMBER: builtins.int
+        SILENT_FIELD_NUMBER: builtins.int
         @property
         def pairs(
             self,
         ) -> 
google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___KeyValue]:
             """(Required) The config key-value pairs to set."""
+        silent: builtins.bool
+        """(Optional) Whether to ignore failures."""
         def __init__(
             self,
             *,
             pairs: collections.abc.Iterable[global___KeyValue] | None = ...,
+            silent: builtins.bool | None = ...,
         ) -> None: ...
-        def ClearField(self, field_name: typing_extensions.Literal["pairs", 
b"pairs"]) -> None: ...
+        def HasField(
+            self, field_name: typing_extensions.Literal["_silent", b"_silent", 
"silent", b"silent"]
+        ) -> builtins.bool: ...
+        def ClearField(
+            self,
+            field_name: typing_extensions.Literal[
+                "_silent", b"_silent", "pairs", b"pairs", "silent", b"silent"
+            ],
+        ) -> None: ...
+        def WhichOneof(
+            self, oneof_group: typing_extensions.Literal["_silent", b"_silent"]
+        ) -> typing_extensions.Literal["silent"] | None: ...
 
     class Get(google.protobuf.message.Message):
         DESCRIPTOR: google.protobuf.descriptor.Descriptor
diff --git a/python/pyspark/sql/connect/session.py 
b/python/pyspark/sql/connect/session.py
index 3f1663d06850..59349a17886b 100644
--- a/python/pyspark/sql/connect/session.py
+++ b/python/pyspark/sql/connect/session.py
@@ -200,34 +200,26 @@ class SparkSession:
             for i in range(int(os.environ.get("PYSPARK_REMOTE_INIT_CONF_LEN", 
"0"))):
                 init_opts = 
json.loads(os.environ[f"PYSPARK_REMOTE_INIT_CONF_{i}"])
 
+            # The options are applied after session creation,
+            # so options ["spark.remote", "spark.master"] always take no 
effect.
+            invalid_opts = ["spark.remote", "spark.master"]
+
             with self._lock:
+                opts = {}
+
+                # Only attempts to set Spark SQL configurations.
+                # If the configurations are static, it might throw an 
exception so
+                # simply ignore it for now.
                 for k, v in init_opts.items():
-                    # the options are applied after session creation,
-                    # so following options always take no effect
-                    if k not in [
-                        "spark.remote",
-                        "spark.master",
-                    ] and k.startswith("spark.sql."):
-                        # Only attempts to set Spark SQL configurations.
-                        # If the configurations are static, it might throw an 
exception so
-                        # simply ignore it for now.
-                        try:
-                            session.conf.set(k, v)
-                        except Exception as e:
-                            logger.warn(f"Failed to set configuration {k} due 
to {e}")
+                    if k not in invalid_opts and k.startswith("spark.sql."):
+                        opts[k] = v
 
-            with self._lock:
                 for k, v in self._options.items():
-                    # the options are applied after session creation,
-                    # so following options always take no effect
-                    if k not in [
-                        "spark.remote",
-                        "spark.master",
-                    ]:
-                        try:
-                            session.conf.set(k, v)
-                        except Exception as e:
-                            logger.warn(f"Failed to set configuration {k} due 
to {e}")
+                    if k not in invalid_opts:
+                        opts[k] = v
+
+                if len(opts) > 0:
+                    session.conf._set_all(configs=opts, silent=True)
 
         def create(self) -> "SparkSession":
             has_channel_builder = self._channel_builder is not None
diff --git a/sql/connect/common/src/main/protobuf/spark/connect/base.proto 
b/sql/connect/common/src/main/protobuf/spark/connect/base.proto
index c308c7e21b66..74413509ebc1 100644
--- a/sql/connect/common/src/main/protobuf/spark/connect/base.proto
+++ b/sql/connect/common/src/main/protobuf/spark/connect/base.proto
@@ -525,6 +525,9 @@ message ConfigRequest {
   message Set {
     // (Required) The config key-value pairs to set.
     repeated KeyValue pairs = 1;
+
+    // (Optional) Whether to ignore failures.
+    optional bool silent = 2;
   }
 
   message Get {
diff --git 
a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/SparkConnectConfigHandler.scala
 
b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/SparkConnectConfigHandler.scala
index c5e484e022bc..06bc24b6ccae 100644
--- 
a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/SparkConnectConfigHandler.scala
+++ 
b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/SparkConnectConfigHandler.scala
@@ -73,11 +73,21 @@ class SparkConnectConfigHandler(responseObserver: 
StreamObserver[proto.ConfigRes
   private def handleSet(
       operation: proto.ConfigRequest.Set,
       conf: RuntimeConfig): proto.ConfigResponse.Builder = {
+    val silent = operation.hasSilent && operation.getSilent
     val builder = proto.ConfigResponse.newBuilder()
     operation.getPairsList.asScala.iterator.foreach { pair =>
       val (key, value) = SparkConnectConfigHandler.toKeyValue(pair)
-      conf.set(key, value.orNull)
-      getWarning(key).foreach(builder.addWarnings)
+      try {
+        conf.set(key, value.orNull)
+        getWarning(key).foreach(builder.addWarnings)
+      } catch {
+        case e: Throwable =>
+          if (silent) {
+            builder.addWarnings(s"Failed to set $key to $value due to 
${e.getMessage}")
+          } else {
+            throw e
+          }
+      }
     }
     builder
   }


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

Reply via email to