https://kotlinlang.org logo
#graphql-kotlin
Title
# graphql-kotlin
b

bjartek

01/09/2020, 6:05 PM
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

Dariusz Kuc

01/09/2020, 6:20 PM
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

bjartek

01/09/2020, 6:31 PM
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

Dariusz Kuc

01/09/2020, 7:42 PM
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

bjartek

01/09/2020, 7:45 PM
Copy code
fun company(dfe: DataFetchingEnvironment): CompletableFuture<DataFetcherResult<Company>?> = dfe.load<Int, Company>(companyId)
d

Dariusz Kuc

01/09/2020, 7:45 PM
with coroutines (and reactor) you have better control over your asynchrony and parallelism
b

bjartek

01/09/2020, 7:45 PM
Yupp, and that would be preferable. I just want to see if i can get partial results to work first 🙂
d

Dariusz Kuc

01/09/2020, 7:45 PM
i'd assume that would be
Copy code
fun company(dfe: DataFetchingEnvironment): CompletableFuture<DataFetcherResult<Company?>> = dfe.load<Int, Company>(companyId)
b

bjartek

01/09/2020, 7:45 PM
I can try that yes and see if that works
d

Dariusz Kuc

01/09/2020, 7:45 PM
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

bjartek

01/09/2020, 7:46 PM
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

Dariusz Kuc

01/09/2020, 7:55 PM
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

bjartek

01/09/2020, 7:57 PM
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

Dariusz Kuc

01/09/2020, 7:57 PM
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

bjartek

01/09/2020, 8:03 PM
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

Dariusz Kuc

01/09/2020, 8:05 PM
any feedback is appreciated so if you find something that doesn't work or is hard to use please let us know
b

bjartek

01/09/2020, 8:16 PM
will do
here is the code that I have for now.
d

Dariusz Kuc

01/09/2020, 9:33 PM
nice
30 Views