Jaime
04/26/2022, 2:10 AMApolloClient.Builder()
.serverUrl(BuildConfig.HOST)
.okHttpClient(okHttpClient.build())
.autoPersistedQueries(
httpMethodForHashedQueries = HttpMethod.Get,
httpMethodForDocumentQueries = HttpMethod.Get,
)
.normalizedCache(cacheFactory)
.addInterceptor(SessionInterceptor(context))
.addInterceptor(LanguageInterceptor())
.build()
Query
val queryResult = query(query).fetchPolicy(CacheFirst).execute()
Methods normalizedCache and fetchPolicy not found in 3.2.1Jaime
04/30/2022, 6:29 AMStandaloneCoroutine was canceled
it only happens to me when a specific api is consumed
this is my apollo configuration
val logging = HttpLoggingInterceptor()
logging.level = HttpLoggingInterceptor.Level.NONE
if (BuildConfig.DEBUG) {
logging.level = HttpLoggingInterceptor.Level.BODY
}
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(logging)
.connectTimeout(8, TimeUnit.SECONDS)
.readTimeout(8, TimeUnit.SECONDS)
.writeTimeout(8, TimeUnit.SECONDS)
apolloClient = ApolloClient.Builder()
.serverUrl(
BuildConfig.HOST
)
.okHttpClient(
okHttpClient.build()
)
.normalizedCache(
SqlNormalizedCacheFactory(context, "h_apollo.db"),
writeToCacheAsynchronously = true
)
.addInterceptor(
SessionInterceptor(context)
)
.addInterceptor(
LanguageInterceptor()
)
.build()
HttpLogginInterceptor print
<-- HTTP FAILED: java.io.IOException: Canceled
Jan Skrasek
05/03/2022, 8:03 AMimplementation("com.apollographql.apollo3:apollo-gradle-plugin:3.2.2")
but I fail to use any type from Apollo plugin (ApolloExtension, etc.), no autocompletion, class is not "visible".
Any idea why? I use convention plugin and configure other tools (like Detekt) and it works like a charm.John O'Reilly
05/03/2022, 4:51 PMwatch
is being used to drive UI.....I think someone mentioned before that separately calling say execute
on a query will cause cache to be updated and any UI observing the flow from watch
will get the update?Stylianos Gakis
05/04/2022, 3:19 PMMapTestNetworkTransport
instead. So I was wondering, since I don’t think there’s a way to do that right now, would it make sense to introduce a way to map an Operation to a result using something similar to registerTestResponse but by accepting an operation no matter what the inputs?
Otherwise the annoying part is that I have to in cases like the one I linked above, go inside the Activity and check what is being passed inside those queries and copy it inside the tests. But in the tests that I am doing right now I am mostly interested in how the UI reacts to a particular response, not that I am also sending the correct query.
With all that said, I know that the queue approach also exists, which doesn’t care for what the query was, but simply responds with specific things in order, but in many of these tests I do want the mapping functionality of at least the Operation type to the response, just not interested in what the input to that Operation was.
Does my idea make sense? Does it sound reasonable? Would it even be feasible? Should I reconsider the approach I’m taking maybe? If you have any sort of input I’d love to hear it.ephemient
05/07/2022, 10:31 AMvoid com.apollographql.relocated.vi.finallyStart(int)
how should I debug this? I don't see an un-relocated plugin or a mapping to at least track down what this isJan Skrasek
05/10/2022, 9:39 AMval data = UserDataQuery.Data {
viewer = userViewer {
userId = "userId"
identity = identity {
email = "<mailto:jon.snow@example.com|jon.snow@example.com>"
name = name {
first = "Jon"
last = "Snow"
}
}
preferredTrips = preferredTrips {
edges = listOf(edge { node = node { kind = "MUSIC" } })
}
}
}
This was my first attempt:
val data = UserDataQuery.Data {
userViewer {
userId = "userId"
identity {
email = "<mailto:jon.snow@example.com|jon.snow@example.com>"
name {
first = "Jon"
last = "Snow"
}
}
preferredTrips {
edge { node { kind = "MUSIC" } }
}
}
}
Have you considered something like this?Seb Jachec
05/10/2022, 10:11 AMMemoryCacheFactory
& SqlNormalizedCacheFactory
chained together, and doNotStore(true)
is used on an Apollo (3.3.0) query with a CacheOnly
fetch policy, would this prevent the memory cache being populated if only the SQL cache was read from?bod
05/17/2022, 9:55 AMJune 17th, 2022.
It should take no longer then 10 minutes
and every response will be used to help us better understand your use of Apollo Client as well as what type of features and functionality you are looking for in the future.
Thank you! 🙏
The survey is anonymous and the data will only used for directional product decisions, feature prioritization and the long term planning of our Client roadmaps.
Stylianos Gakis
05/17/2022, 12:47 PMStylianos Gakis
05/17/2022, 1:41 PMCacheOnly
refetchPolicy instead CACHE_FIRST
. To keep behavior unchanged, set a refetchPolicy
on your watchers:”
But the snippet directly under it shows subscribe
instead of watch()
. Is this wrong in the sense that it should be .watch()
instead, or should the title of the section be subscriptions
? I am kinda confused at that part of the document.Stylianos Gakis
05/18/2022, 3:47 PMenum CrossSellType {FOO \n BAR}
. Apollo {} is configured with sealedClassesForEnumsMatching.set(listOf("CrossSellType", ...))
and then the generated code looks like this "type" to resolve("type", CrossSellType.type.notNull(), knownValues().map { it.name }),
.
Problem is, knownValues() returns a list of <CrossSellType> which is in fact a sealed class now, not an enum, so .name
isn’t resolving, it’s red.
On Apollo 3.3.0 rn, can’t really test earlier versions as a lot of other things will be red.Stylianos Gakis
05/19/2022, 7:50 AMOperation.Data
and I would like to get their Json String representation. I have kind of by accident stumbled upon this function which is jvm only [1] and I think this almost is what I am looking for.
However just had a question, there isn’t a toJsonString
equivalent in there which is what I would like to get instead. And I can’t quite build my own version of it locally since I adapter()
is private in that file and I don’t feel like copying that one into our project.
I guess what I can do instead locally is imitate what the Adapter<D>.toJsonString is doing, with something like this right?
fun Operation.Data.toJsonString(
scalarTypeAdapters: CustomScalarAdapters = CustomScalarAdapters.Empty,
indent: String? = null,
): String {
val buffer = Buffer()
val jsonWriter = BufferedSinkJsonWriter(buffer, indent)
toJson(jsonWriter, scalarTypeAdapters)
return buffer.readUtf8()
}
But optimally, I’d like that function to be available to me from the library, where it can use the private adapter()
function and not have to deal with buffers etc. in my local code. I am definitely not super confident with using them.
So in short, do you think it’d fit to have a function with this body directly under this one, or should I just do the workaround I posted above (or something else if it is wrong of course)
fun Operation.Data.toJsonString(customScalarAdapters: CustomScalarAdapters = CustomScalarAdapters.Empty, indent: String? = null): String {
return adapter().toJsonString(this, customScalarAdapters, indent)
}
Random question:
[1] Is this due to the getDeclaredField
calls etc? Is that using reflection only available on the JVM or something?Stylianos Gakis
05/19/2022, 9:39 AMStylianos Gakis
05/23/2022, 2:51 PMthis.activeFrom = JavaLocalDateAdapter.toJsonString(
LocalDate.of(2021, 4, 11), // I guess no need to pass anything for customScalarAdapters here
)
And then this line inside build should take are of it right? "activeFrom" to resolve("activeFrom", LocalDate.type, emptyList()),
And a couple of thoughts if I assume that this is the way to do it. I’d of course optimally like to be able to just give it the object itself, but maybe this isn’t possible with the way the test builders are made. Maybe some convenience function could be generated that does this for us?Filip Wiesner
05/24/2022, 11:03 AMfeature/home/GetHome.graphql
and shared/CategoryFragment.graphql
. These files are each in it's own service
so that I can specify a package name to the generated files. Now I want to access CategoryFragment
from GetHome
file but it errors out with `Cannot find fragment `Category``.
Or maybe different question with the same outcome. Can I specify the package name of generated file more granularly so that the package names of different queries, mutations and fragments more resemble my defined project package structure?Stylianos Gakis
05/24/2022, 4:16 PMJavaLocalDateAdapter.toJsonString(LocalDate.of(2021, 4, 11))
I get back the string ""2021-04-11""
.
Now if I do a test case like this:
val localDate = LocalDate.of(2021, 4, 11)
val jsonRepresentation = JavaLocalDateAdapter.toJsonString(localDate)
val buffer = Buffer().write(jsonRepresentation.encodeUtf8())
val jsonReader = BufferedSourceJsonReader(buffer)
val parsedAgain = JavaLocalDateAdapter.fromJson(jsonReader, CustomScalarAdapters.Empty)
assertThat(parsedAgain).isEqualTo(localDate)
It passes fine as expected.
However when I am actually using it on the builder, it crashes at the adapter, since it tries to then parse ""2021-04-11""
directly, and LocalDate fails to do so. In this line in particular, the nextString!!
returns the value with those double quotes and it fails.
In the code snippet I put above, the encodeUtf8() part seems to turn it into a string with a single quote which makes this work, and maybe this isn’t happening in the test builders code? I am not quite sure what piece of the puzzle is going wrong, so I am posting this here in case you may have a better idea.
Edit: For people who might read this at some future time and might be confused. I had simply misread that it was giving me back a String with double quoted strings, but it was just that in the debugger view in IntelliJ, to indicate a string it wraps it with quotations in the UI. The String I got back was in fact "2021-04-11"
as expected and the workaround for the test builders was to strip the ‘“’ from the start and the end of the resulting string. This resulted in the String 2021-04-11
which was correctly parsed from the LocalDate.parseagrosner
05/24/2022, 6:00 PMStylianos Gakis
05/25/2022, 8:05 AMStylianos Gakis
05/25/2022, 2:18 PMstatus
is ContractStatus!
which is a union with the three things you saw in the query among others. This worked fine somehow, since the __typename in the constructor put val __typename: String = "ContractStatus"
and parsing it was no problem.
In 3.x, we do not get that for free, and I need to go and put the correct __typename to each and every one of those constructors, and I am trying to avoid this if possible. I’ve put __typename = ""
everywhere to make it compile, and it works for most cases, but not for one like here where even the test builder can’t automatically populate the __typename and I need to specify it myself, like here.
So now due to this change, I would need to either adopt the testBuilders which handle this for me by forcing me to chose the typename when I need to, and even give me a comment above it with the possible correct options in the generated code (Nice work there, super convenient). Or I need to just go and hunt all the places where this problem happens and manually put in the correct __typename in all these places.
Am I missing something in this migration story? I understand that the way we construct the Data objects in our tests might be a bit unorthodox, hence an easy solution may not exist, so just asking here for ideas 🤗Vsevolod Kaganovych
05/26/2022, 10:39 AMtype
value. But apollo-kotlin generates the type
field inside the companion object and inserts it in knownValues()
. Is there a way to avoid/ignore it, cause the project doesn't compile in this case? Version - 3.3.0Vsevolod Kaganovych
05/27/2022, 1:30 PMHttpLoggingInterceptor
breaks the multipart request. If I don't add it, the request works. The exception is the same as here https://github.com/apollographql/apollo-kotlin/issues/2912, but I don't add 2 of them. I have my custom interceptor for authorization and logging. Any ideas?Vsevolod Kaganovych
05/27/2022, 4:17 PMmutation uploadFile($id: String!, $files: [Upload!]!)
The request is built like this
val upload = DefaultUpload.Builder()
.content(file)
.fileName(file.name)
.build()
val mutation = UploadFileMutation(id = recommendationId, files = listOf(upload))
But the backend tells me, that the received files
field is not an array and returns an error to me. Are there any modifications for the multipart request if there's only 1 item to be sent?Stylianos Gakis
05/27/2022, 11:25 PM"variables" to resolve("variables", some type, emptyList(), { ctors here })
and the list of constructors is of all the possible things this could be. But some of those alternatives are builders that require the __typename to be specified, so it crashes when it tries to resolve them all. I then need to go back that stacktrace and find the last reference to my code to see which field it is that I need to define but isn’t there.
Where this happens is places where there is a field which inside the generated builder has the type List<Map<String, Any?>>
, so it’s not nullable and it needs to be specified. (The type inside the schema is [SomeType!]!.
I am sure I’ve not explained this very well, but just wanted to type it out here for now and if it makes sense to you that’d be awesome, if not I will try to make a better explanation some other day 😅Stylianos Gakis
06/02/2022, 1:58 PMStylianos Gakis
06/03/2022, 9:03 AMalso
block right? In general I was thinking about this and I realize I can’t answer this question with much confidence, so I thought I’d ask here 😄Nick
06/09/2022, 12:26 AM{
hero {
friends {
person {
home {
kitchen {
stove {
brand
}
}
}
}
}
}
}
Stylianos Gakis
06/13/2022, 8:25 AMStylianos Gakis
06/13/2022, 3:15 PMcom.apollographql.apollo3.exception.SubscriptionOperationException: Operation error ChatMessage
where ChatMessage is a subscription. And I don’t quite know where to go from there, hence here I am if you have any obvious thing I am missing.Seb Jachec
06/13/2022, 3:57 PMprint
statements before/after query.execute()
) shortly after app launch. From inspecting the SQL DB, I’d guess this query reads ~2,000 SQL records worth of data.
We’re using Apollo’s in-memory cache (10MB limit), chained with the SQL normalized disk cache, in a KMM app. Inspecting the cache seems easy on Android, from where I can see our disk cache DB file is ~1.1MB, with ~2150 records in total during an average flow through our app (launch app, query for account, query user’s paginated items). Each ‘item’ has ~15 immediate fields, most of which are nested fragments/objects.
We’re creating a flow { .. }
, and using withContext(Dispatchers.Main) { .. }
inside this to execute the Apollo query for items and receive the response (we later perform some other operations within that flow, after emitting the queried cache-only items). Downstream shared view models collect via IO
(Android)/`Default` Dispatcher (iOS), and further downstream, platform view models collect from shared view models on the main dispatcher/thread to present UI.