What about handling partial errors? Lets say I hav...
# graphql-kotlin
b
What about handling partial errors? Lets say I have an Employee that has a company and loading one Company fails. I still want data for all the Employees and companies that have data, but an error in the case where it does not load
d
depends how you structure your schema
if your query is returning a list of employees and each one of them is associated to a company (which fetching may fail)
you will need to return a wrapper that contains both data and errors
there is a problem that if company is not null
that is not a valid response so it is not really a partial
you would have to return
DataFetcherResult
(see https://www.graphql-java.com/documentation/v13/execution/)
b
Thanks for the information. Will look into it
If i have a function that resolves a property and it returns a CompletableFuture how do I then signal that this should be optional in the schema?
d
since
CompletableFuture
is a wrapper around the actual response I'd assume something like
Copy code
fun whatever(): CompletableFuture<Whatever?>
should work
note that completable future just runs on whatever thread it is currently executing (unless configured differently)
b
Copy code
fun company(dfe: DataFetchingEnvironment): CompletableFuture<DataFetcherResult<Company>?> = dfe.load<Int, Company>(companyId)
d
with coroutines (and reactor) you have better control over your asynchrony and parallelism
b
Yupp, and that would be preferable. I just want to see if i can get partial results to work first 🙂
d
i'd assume that would be
Copy code
fun company(dfe: DataFetchingEnvironment): CompletableFuture<DataFetcherResult<Company?>> = dfe.load<Int, Company>(companyId)
b
I can try that yes and see if that works
d
i.e. that ? is on company and not data fetcher result
not really a big fan of those wrappers and would love to have some nicer solution
b
Agreed
Would it make sense to be able to say to a suspended function that if this throws and error I want to report and error and allow optional reponse? Or keep the current behavior of just erroring out the entire query if there is an error?
Victory!
Copy code
{
  "data": {
    "employees": [
      {
        "name": "Mike",
        "company": {
          "id": 1,
          "name": "FirstCompany"
        }
      },
      {
        "name": "John",
        "company": {
          "id": 1,
          "name": "FirstCompany"
        }
      },
      {
        "name": "Steve",
        "company": null
      }
    ]
  },
  "errors": [
    {
      "locations": [],
      "path": null,
      "errorType": "DataFetchingException",
      "extensions": {},
      "message": "Exception while fetching data () : java.lang.RuntimeException: Failed"
    }
  ]
}
not complete victory though, missing the path and stuff from that exception
load is now this
Copy code
inline fun <Key, reified Value> DataFetchingEnvironment.load(key:Key): CompletableFuture<DataFetcherResult<Value?>> {
    val loaderName = "${Value::class.java.simpleName}DataLoader"
    return this.getDataLoader<Key, Value>(loaderName).load(key).thenApply {
        DataFetcherResult.newResult<Value>().data(it).build()
    }.exceptionally { 
        DataFetcherResult.newResult<Value>().error(SimpleKotlinGraphQLError(it)).build() 
    }

}
I guess i could make my own FunctionDataFetcher and get that working without all the wrappers?
d
Would it make sense to be able to say to a suspended function that if this throws and error I want to report and error and allow optional reponse? Or keep the current behavior of just erroring out the entire query if there is an error?
It really depends on your use case - errors could be critical or not, if returned data is not useable by the end user then it should fail the entire qwuery
b
Yupp. We already use Graphql with com.graphql-java-kickstart:graphql-spring-boot-starter and I am just looking into how I can try to get the same results as we do there. Thanks a lot for your help
👍 1
If you want a peak our code is here https://github.com/Skatteetaten/gobo
👍 1
d
not complete victory though, missing the path and stuff from that exception
you should be able to get that through custom exception handler or by populating it in the data loader error handling block
I guess i could make my own FunctionDataFetcher and get that working without all the wrappers?
you definitely can create custom data fetcher (we do in order to correctly build our coroutine context) but unsure if it will help much with the data loaders + error handling
b
will let you know if we figure something out
Not sure if I find time to change to your sollution but it has some merrit I belive
d
any feedback is appreciated so if you find something that doesn't work or is hard to use please let us know
b
will do
here is the code that I have for now.
d
nice