by_overview.rb 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. # Copyright (C) 2012-2025 Zammad Foundation, https://zammad-foundation.org/
  2. module Gql::Queries
  3. class Tickets::Cached::ByOverview < BaseQuery
  4. include Gql::Concerns::HandlesOverviewCaching
  5. description 'Fetch tickets of a given ticket overview'
  6. # These arguments (and the ones from pagination such as first:) are part of the cache key.
  7. argument :overview_id, GraphQL::Types::ID, loads: Gql::Types::OverviewType, description: 'Overview ID'
  8. argument :order_by, String, required: false, description: 'Set a custom order by'
  9. argument :order_direction, Gql::Types::Enum::OrderDirectionType, required: false, description: 'Set a custom order direction'
  10. argument :cache_ttl, Integer do
  11. description 'How long to cache the overview data, in seconds. This will be part of the cache key so that different durations get different caches.'
  12. end
  13. # The following arguments will not be part of the cache key.
  14. argument :renew_cache, Boolean, required: false, description: 'Force a refresh of the cache content.'
  15. argument :known_collection_signature, String, required: false do
  16. description 'Signature of a known collection state on the front end. If there is the same state still on the server, it will not return edges data.'
  17. end
  18. type Gql::Types::TicketType.custom_connection_type(type_class: Gql::Types::BaseCachedConnection, type_name: 'CachedTicketConnection'), null: false
  19. def self.register_in_schema(schema)
  20. schema.field graphql_field_name, resolver: self do
  21. # Frontend needs to fetch all visible tickets at once, that can be up to 1000.
  22. # Reduce the calculated complexity to make this possible for the current query.
  23. complexity lambda { |_ctx, _args, child_complexity|
  24. (child_complexity / 10).to_i
  25. }
  26. end
  27. end
  28. def resolve(cache_ttl:, overview:, renew_cache: false, order_by: nil, order_direction: nil, known_collection_signature: nil)
  29. if renew_cache
  30. context.scoped_set!(:renew_cache, true)
  31. end
  32. maybe_cached_value(cache_ttl:, overview:, order_by:, order_direction:)
  33. end
  34. def maybe_cached_value(cache_ttl:, overview:, order_by:, order_direction:)
  35. cache_fragment(path_cache_key: filtered_path_cache_key, object_cache_key: object_cache_key(overview), expires_in: cache_ttl) do
  36. # This will fetch tickets with 'overview' permissions, which logically include 'read' permissions.
  37. ::Ticket::Overviews.tickets_for_overview(overview, context.current_user, order_by: order_by, order_direction: order_direction)
  38. end
  39. end
  40. # We need to arguments. This can currently only be achieved with a hack,
  41. # see https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/issues/133 (perhaps it can be improved
  42. # after this is solved).
  43. def filtered_path_cache_key
  44. GraphQL::FragmentCache::CacheKeyBuilder.new(query: context.query, path: context.current_path).send(:path_cache_key)
  45. .sub(%r{,renew_cache:(?:true|false)?}, '')
  46. end
  47. end
  48. end