While trying to finally close #2932625: Fix query count after query builder refactor, I started to look into the underlying functionality. I did not realize that we were doing anything to count queries. In fact, I think I can remember early discussions where we explicitly decided that providing counts was an anti-pattern and would encourage broken client implementations (but I could also just be dreaming that).
As far as I can tell, we're using using ResourceType::includeCount() to determine if we should run a count entity query, then adding that count to the EntityCollection which would only get serialized if includeCount() returned TRUE.
However, the current implementation of includeCount only every returns FALSE!:
public function includeCount() {
// By default, do not return counts in collection queries.
return FALSE;
}
This means we're supporting a lot of code paths that can never be executed unless JSON API Extras has overridden the resource type. I'm okay with that, if it's for a really good reason™️.
However, in this case, I think we're really doing a disservice to our consumers.
The only reason I can think of for including a page count is to try to guess the number of requests to make on the client side, rather than relying on the next links already in the document. It encourages clients to manually construct links and it can potentially really trip up developers when any kind of access control is involved.
This unnecessarily forces us to maintain BC for our URL structure, which "in theory", shouldn't be necessary (for discussion elsewhere ;) ). Worst of all, It promises something we can't deliver on. It's bad DX.
I believe we ought to remove this feature before we put JSON API in core and that we should consider how we can best provide resources for developers to grok best-practices for pagination and making use of all the link information we provide, rather than leading them astray.
To be clear, I don't want this to be construed as a blocker to core inclusion. I just think it's we should have the discussion sooner rather than later and the longer we wait, the less freedom we have.
Comments
Comment #2
gabesulliceComing from #2932625-17: Fix query count after query builder refactor. If we do decide that we should continue to support this, we need to add explicit test coverage.
Comment #3
gabesulliceFTR, I don't think this is a blocker to core inclusion and is absolutely not critical. It's just a discussion :)
Comment #4
e0ipsoI am not opposed to removing this feature and move it completely to JSON API Extras. However adding the necessary extensibility to allow that may introduce more code paths than the ones that we remove. On top of that we will have to worry about other contribs using those extensibility outlets.
We are not doing much to allow this feature inside of jsonapi, right?
I can expect someone decorating the resource type repository service to toggle that on without needing JSON API extras. However there is no documentation on how to do that or the fact that you can do it. Maybe worth mentioning in the new Pagination section of the docs?
Comment #5
wim leersThis is a blocker for #2950744: Move relevant test coverage from jsonapi_extras to jsonapi, which blocks #2931785: The path for JSON API to core.
Comment #6
e0ipso@Wim Leers I don't think we should be blocking such an important issue #2931785: The path for JSON API to core on this. My take is, we should continue supporting this until we reach agreement to drop it. I wouldn't want to put everything on hold for this discussion.
FWIW I don't think we should drop the feature, I think it's very important for JSON API to have it. However I'm open to having a discussion.
Comment #7
wim leersSure … but then the question is: how do we test it?
As @gabesullice explained at #2932625-17: Fix query count after query builder refactor:
And therefore #2950744: Move relevant test coverage from jsonapi_extras to jsonapi is blocked on this.
Comment #8
e0ipsoThat is not entirely correct. See #4:
I will take that one. As stated in #4 it only involves decorating the resource type repository. Since it's doable with the codebase as-is, I believe we can un-postpone it.
Comment #9
wim leersRight, I agree, and came to the same conclusion in #2950744: Move relevant test coverage from jsonapi_extras to jsonapi:
I agree that this is the most pragmatic approach, if we still feel that we should keep this feature. I just wanted to get an update in this issue if in the past month (#4 was Feb 7, #5 was Mar 7), thoughts had shifted. If everybody agrees we don't need this feature, then it'd be less work!
Do you mean you want to work on that test coverage? (In #2950744: Move relevant test coverage from jsonapi_extras to jsonapi.)
Comment #10
e0ipsoI, for one, think we need this feature. I use it fairly often. Specially around consuming a paginated list of elements in a performant way.
Comment #11
gabesullice@e0ipso, can you explain? I'm assuming that you're creating subrequests by "building" URLs for subsequent pages, is that the case?
If so, I'd love to chat about how to do that differently without losing any performance :) I'm almost certain that it's possible (but maybe you'll prove me wrong).
Then, if we can make it work, would you consider dropping this feature? I truly do believe it's an anti-pattern and that it's not a necessary feature, it just a matter of demonstrating a "better" approach.
Comment #12
e0ipsoWe can meet. Will that proposal involve a browser? Because non browser scenarios is a must atm.
Comment #13
wim leersBased on #11, I think it's better we all hold off working on testing the count stuff in
jsonapiuntil after @gabesullice and @e0ipso have had that meeting :)Comment #14
gabesulliceIn our discussion, we agreed that it's necessary to understand pagination information in advance so that one can send parallel requests.
My understanding was that: solely relying on a "next" link means one can't rely on the next link if you need to send parallel requests. I.e. if you don't know how many pages to send, you risk "overshooting" the last page. Our call ended before we could really settle on anything.
We just had a chat, which I'll summarize below.
Comment #15
e0ipsoMost sites will never experience this problem.
No, no. I won't take a unilateral decision. This decision is also yours to take.
I hope you are wrong.
Ultimately what I care is about the features. Honestly, if it didn't cost us a separate query every time the count would not be optional. If there is a way to provide the total count and a full pagination that is different to what we already have, then I don't care about details. If the proposal is to just drop the features, then I don't agree.
Until consensus is reached I will assume things stay the same. I will provide test coverage for this (at some point). If later on we decide to drop this (via BC break), then we can remove the test coverage as well.
Comment #16
e0ipsoSince the proposal in #11 couldn't provide the features we expected, I'm unblocking #2950744: Move relevant test coverage from jsonapi_extras to jsonapi based on #15.
Comment #17
wim leersI have two questions:
Could you elaborate on this?
lastlink? i.e. why does one think it's a viable compromise/solution, and the other thinks it's not?Comment #18
gabesulliceTo be clear, I just was deferring to you so as not to be an obstructionist, not to force you to take a decision, I think that came off more poorly than I realized.
Comment #19
e0ipsoPlease, don't worry too much about that. I assume respect and good intentions when interpreting your words. I hope you see that of me. And that you assume that from me too :-*
#17.1: Most sites don't have contrived access rules that cannot possibly be expressed in a JSON API filter.
#17.2: I doesn't allow a super common use case in web design: Showing 15 items of %COUNT%. Whereas adding a count and a last link does.
More importantly I don't see why this creates such a big hassle. It is a super common use case, it has a very little impact in the codebase and it's optional. I don't see the big win in removing it, even after the previous comments. In addition to all that we've been supporting this since the first dev releases, removing support for this seems like an unnecessary regression (even after we marked all the things as internal at some point).
In other news we have test coverage for both counting and enabling counts in https://www.drupal.org/project/jsonapi/issues/2950744#comment-12519567.
Comment #20
wim leersSites use
content_moderationcannot easily express "is published" in a JSON API filter. So I think this will change rather significantly and quickly!But the total count is going to be unreliable. Also, I think this is increasingly rare actually … Gmail hasn't showed the total count for years. Twitter doesn't show it. Facebook doesn't show it. (I personally do like seeing that total count though! But only if it's accurate.)
The big win lies in the fact that this the result is unreliable, and that once this is in core, we really can't remove it, so we'll be required to support something unreliable. Bug reports will be filed, and some people will want it to work one way, others will want it to work the other way. It'll be painful to support.
RE: in other news: I saw, GREAT! Thank you :) I reviewed/responded/rerolled there: #2950744-6: Move relevant test coverage from jsonapi_extras to jsonapi.
Comment #21
e0ipsoIt seems to boil down to this. And I understand the frustration, but I totally disagree with the approach.
I think it's best to be accurate most of the time and document the inaccuracies, rather than throw our arms on the air and regress the feature. I wonder how the Views module is doing it, since it offers aggregation capabilities as well. I don't think we should open an issue to remove aggregation capabilities if they are not 100% accurate 100% of the time.
My take is that this is a tool that has limitations and should be documented and used as such.
Comment #22
wim leersThis is indeed where we fundamentally disagree :)
I would not ship this feature. Because documenting the inaccuracies does not work in practice in the real world IMHO: many people will either not read it because they don't want to, or can't find it.
I've also shipped every possible experimental feature in the past with my contrib modules, but I now firmly believe in only shipping features that are rock solid — see https://wimleers.com/article/simplicity-maintainability-cdn-module-drupal-8 if you're interested :)
Comment #23
gabesulliceComment #24
e0ipsoI guess it is. I don't have any other arguments, other than this is certainly a common request in many projects. Saying, your requirements are wrong or your designs don't meet the real world expectations may not be inaccurate, but that doesn't make it less real. This is a need people have, even if it can't work perfectly.
As a compromise to unblock this I'm not opposed to remove all traces from counting in JSON API, as long as we also provide an accompanying patch for JSON API Extras to keep counts working.
Comment #25
wim leersComment #26
br0kenExcuse me for interrupting you :)
Just wanted to say that I use this feature in several projects and would like to have a clear path for implementing it as a custom if it will be removed.
Comment #27
br0kenAlso, recently I removed JSON:API Extras from one project and now working on a patch to return a configurable value from that "static" method.
Edit:
See #3104408: Allow to include a total count of items to collection responses.
Comment #29
bbralaThis issue is superseeded by #3104408: Allow to include a total count of items to collection responses since we are actually implementing a public API to support this. :)