-
Notifications
You must be signed in to change notification settings - Fork 611
feat: dataconnect: DataConnectOperationException added to support partial errors #6794
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…se DataConnectOperationException instead of DataConnectException
📝 PRs merging into main branchOur main branch should always be in a releasable state. If you are working on a larger change, or if you don't want this change to see the light of the day just yet, consider using a feature branch first, and only merge into the main branch when the code complete and ready to be released. |
1 similar comment
📝 PRs merging into main branchOur main branch should always be in a releasable state. If you are working on a larger change, or if you don't want this change to see the light of the day just yet, consider using a feature branch first, and only merge into the main branch when the code complete and ready to be released. |
Coverage Report 1Affected Products
Test Logs |
The public api surface has changed for the subproject firebase-dataconnect_api.txt: Please update the api.txt files for the subprojects being affected by this change by running ./gradlew ${subproject}:generateApiTxtFile. Also perform a major/minor bump accordingly. |
1 similar comment
The public api surface has changed for the subproject firebase-dataconnect_api.txt: Please update the api.txt files for the subprojects being affected by this change by running ./gradlew ${subproject}:generateApiTxtFile. Also perform a major/minor bump accordingly. |
Test Results 66 files + 2 66 suites +2 1m 16s ⏱️ +4s Results for commit 3b00fb4. ± Comparison against base commit 75be716. This pull request removes 40 and adds 50 tests. Note that renamed tests count towards both.
♻️ This comment has been updated with latest results. |
Size Report 1Affected Products
Test Logs |
The public api surface has changed for the subproject firebase-dataconnect_api.txt: Please update the api.txt files for the subprojects being affected by this change by running ./gradlew ${subproject}:generateApiTxtFile. Also perform a major/minor bump accordingly. |
# Conflicts: # firebase-dataconnect/CHANGELOG.md
The public api surface has changed for the subproject firebase-dataconnect_api.txt: Please update the api.txt files for the subprojects being affected by this change by running ./gradlew ${subproject}:generateApiTxtFile. Also perform a major/minor bump accordingly. |
4 similar comments
The public api surface has changed for the subproject firebase-dataconnect_api.txt: Please update the api.txt files for the subprojects being affected by this change by running ./gradlew ${subproject}:generateApiTxtFile. Also perform a major/minor bump accordingly. |
The public api surface has changed for the subproject firebase-dataconnect_api.txt: Please update the api.txt files for the subprojects being affected by this change by running ./gradlew ${subproject}:generateApiTxtFile. Also perform a major/minor bump accordingly. |
The public api surface has changed for the subproject firebase-dataconnect_api.txt: Please update the api.txt files for the subprojects being affected by this change by running ./gradlew ${subproject}:generateApiTxtFile. Also perform a major/minor bump accordingly. |
The public api surface has changed for the subproject firebase-dataconnect_api.txt: Please update the api.txt files for the subprojects being affected by this change by running ./gradlew ${subproject}:generateApiTxtFile. Also perform a major/minor bump accordingly. |
The public api surface has changed for the subproject firebase-dataconnect_api.txt: Please update the api.txt files for the subprojects being affected by this change by running ./gradlew ${subproject}:generateApiTxtFile. Also perform a major/minor bump accordingly. |
1 similar comment
The public api surface has changed for the subproject firebase-dataconnect_api.txt: Please update the api.txt files for the subprojects being affected by this change by running ./gradlew ${subproject}:generateApiTxtFile. Also perform a major/minor bump accordingly. |
There are two failing GitHub Actions, both of which ave been identified as false positives:
|
...nnect/src/main/kotlin/com/google/firebase/dataconnect/DataConnectOperationFailureResponse.kt
Outdated
Show resolved
Hide resolved
…reResponse.ErrorInfo.PathSegment moved to a top-level class
3555951
to
d036552
Compare
The public api surface has changed for the subproject firebase-dataconnect_api.txt: The public api surface has changed for the subproject firebase-dataconnect: Please update the api.txt files for the subprojects being affected by this change by running ./gradlew ${subproject}:generateApiTxtFile. Also perform a major/minor bump accordingly. |
The public api surface has changed for the subproject firebase-dataconnect_api.txt: Please update the api.txt files for the subprojects being affected by this change by running ./gradlew ${subproject}:generateApiTxtFile. Also perform a major/minor bump accordingly. |
…'postgresql://postgres:postgres@localhost:5432?sslmode=disable'
The public api surface has changed for the subproject firebase-dataconnect_api.txt: Please update the api.txt files for the subprojects being affected by this change by running ./gradlew ${subproject}:generateApiTxtFile. Also perform a major/minor bump accordingly. |
The public api surface has changed for the subproject firebase-dataconnect_api.txt: Please update the api.txt files for the subprojects being affected by this change by running ./gradlew ${subproject}:generateApiTxtFile. Also perform a major/minor bump accordingly. |
…tial errors (#6794) This PR adds the `DataConnectOperationException` class, a subclass of the previously-existing `DataConnectException` class. This new `DataConnectOperationException` class is thrown by invocations of `QueryRef.execute()` and `MutationRef.execute()` in the case where a response _is_ received from the backend, but the response indicates that the operation could not be executed to completion, including the case that the client SDK fails to decode the response to a higher-level object. Other kinds of errors, such as networking errors, will still be reported as they were previously. Client code can catch `DataConnectOperationException` and check its `response` property to get details about any errors that occurred and any data that was received. If the data was able to be decoded, despite the errors, then it will be available. Also the "raw" data (a `Map<String, Any?>`) property will give access to the raw, undecoded data, if any was sent from the backend. This feature is intended to support "partial errors", where an operation can partially succeed and partially fail, and the client application wants to take some special behavior in the case of a partial success. For example, suppose this database schema and connector definition: ``` type Person @table { name: String! } # Notice how both "inserts" use the same ID; this means that one of them # will necessarily fail because you can't have two rows with the same ID. mutation InsertMultiplePeople($id: UUID!, $name1: String!, $name2: String!) { person1: person_insert(data: { id: $id, name: $name1 }) person2: person_insert(data: { id: $id, name: $name2 }) } ``` Here is some code that handles the partial error that will occur if this mutation were to ever be executed: ```kt import com.google.firebase.dataconnect.DataConnectOperationException import com.google.firebase.dataconnect.DataConnectOperationFailureResponse import com.google.firebase.dataconnect.DataConnectPathSegment import com.myapp.myconnector.InsertTwoFoosWithSameIdMutation.Data suspend fun demo(id: UUID, connector: DemoConnector): Data { val result = connector.insertTwoFoosWithSameId.runCatching { execute(id) } result.onSuccess { println("Weird... inserting _both_ entries with ID $id succeeded 🤷") return@demo it.data } val exception = result.exceptionOrNull()!! if (exception !is DataConnectOperationException) { throw exception } // Print warnings messages about which of "foo1" and "foo2" failed to // be inserted by the query. This information is gleaned from the list of // errors provided in the DataConnectOperationFailureResponse. val response: DataConnectOperationFailureResponse<*> = exception.response val errors = response.errors val error1 = errors.firstOrNull { it.path == listOf(DataConnectPathSegment.Field("person1")) } if (error1 == null) { println("Inserting 1st entry with ID $id succeeded") } else { println("Inserting 1st entry with ID $id failed: ${error1.message}") } val error2 = errors.firstOrNull it.path == listOf(DataConnectPathSegment.Field("person2")) } if (error2 == null) { println("Inserting 2nd entry with ID $id succeeded") } else { println("Inserting 2nd entry with ID $id failed: ${error2.message}") } // If decoding the response was actually successful, then return // the decoded response. val data = response.data as? Data if (data != null) { return data } throw exception } ```
This PR adds the
DataConnectOperationException
class, a subclass of the previously-existingDataConnectException
class. This newDataConnectOperationException
class is thrown by invocations ofQueryRef.execute()
andMutationRef.execute()
in the case where a response is received from the backend, but the response indicates that the operation could not be executed to completion, including the case that the client SDK fails to decode the response to a higher-level object. Other kinds of errors, such as networking errors, will still be reported as they were previously.Client code can catch
DataConnectOperationException
and check itsresponse
property to get details about any errors that occurred and any data that was received. If the data was able to be decoded, despite the errors, then it will be available. Also the "raw" data (aMap<String, Any?>
) property will give access to the raw, undecoded data, if any was sent from the backend.This feature is intended to support "partial errors", where an operation can partially succeed and partially fail, and the client application wants to take some special behavior in the case of a partial success.
For example, suppose this database schema and connector definition:
Here is some code that handles the partial error that will occur if this mutation were to ever be executed: