Skip to content

Sprint 2 api-v2 public endpoints and performance follow-ups#713

Merged
jochengcd merged 20 commits into
GrandComicsDatabase:api-v2from
DeusExTaco:feature/api-v2-phase-2
May 31, 2026
Merged

Sprint 2 api-v2 public endpoints and performance follow-ups#713
jochengcd merged 20 commits into
GrandComicsDatabase:api-v2from
DeusExTaco:feature/api-v2-phase-2

Conversation

@DeusExTaco
Copy link
Copy Markdown

Summary

This PR completes the Sprint 2 public api-v2 surface and includes the follow-up performance work needed to keep the new endpoints usable against production-scale data.

Included in this branch:

  • optimize series browse payloads and add the v2 browse index
  • add issues.on_sale_iso_week
  • add public universes endpoints
  • add public groups endpoints
  • add public characters endpoints
  • add public creators endpoints
  • verify the Sprint 2 public schema and route surface
  • fix legacy creator partial-date serialization on production data
  • add browse/delta performance indexes and queryset optimizations for characters, groups, and issues
  • skip exact counts for issue delta-sync requests to avoid multi-second pagination cost

Verification

Code-level verification:

  • ruff check passed on changed files
  • ruff format --check passed on changed files
  • python manage.py check passed in gcd-django-docker-web-1
  • focused filter / serializer / view / model / perf pytest slices passed for the new Sprint 2 work

Manual verification against the running production-copy DB:

  • all Sprint 2 manifests returned 200
  • public schema and route surface were verified
  • perf harness runs were repeated using the same Phase 1 methodology

Representative perf improvements from the manual harness:

  • issues modified__gt=2025-01-01: 2564.6ms -> 48.0ms
  • issues variant_only: 798.0ms -> 85.5ms
  • characters list: 213.5ms -> 48.2ms
  • characters language=en: 181.1ms -> 77.9ms
  • groups list: 180.0ms -> 98.0ms

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds new v2 API endpoints for characters, creators, groups, and universes, and optimizes existing issue and series endpoints with specialized pagination and database indexing. The review feedback recommends enhancing robustness against non-numeric legacy data in integer casts, using .get() instead of .first() for unique lookups to ensure data integrity, and utilizing queryset intersections for more efficient issue filtering.

Comment thread apps/api_v2/filters/creators.py Outdated
Comment thread apps/api_v2/filters/characters.py Outdated
Comment thread apps/api_v2/filters/issues.py Outdated
Comment thread apps/api_v2/filters/characters.py Outdated
'created__lte',
)

def filter_language(self, queryset, name, value):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be made generic ? And used for groups and series ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, why the filter to id and not use the code ?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The public filter still takes the code, so ?language=en stays the API contract. Internally it resolves that once to language_id and filters on the FK id so the list queries avoid the stddata_language join and can use the language-shaped indexes. I added coverage for the SQL shape on all three filters too.

Comment thread apps/api_v2/filters/characters.py Outdated
)
language = django_filters.CharFilter(method='filter_language')
universe = django_filters.NumberFilter(field_name='universe_id')
modified__gt = django_filters.IsoDateTimeFilter(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the modified and created are the same always ?
Can we make a base class with these and make the specific filters for an object be based on that?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call. I moved the standard created/modified range filters into a shared TimestampFilterSet and added a shared field tuple for the Meta.fields lists.

The resource filtersets now only declare their own filters and inherit the common timestamp ones, so the next endpoints can reuse the same base instead of copying that block around.

@jochengcd jochengcd merged commit c800013 into GrandComicsDatabase:api-v2 May 31, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants