pagination

package
v1.55.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 3, 2025 License: BSD-3-Clause Imports: 9 Imported by: 0

Documentation

Overview

Copyright 2025 SGNL.ai, Inc.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetNextCursorFromPageSize

func GetNextCursorFromPageSize(objectsInPage int, pageSize int64, currentCursor int64) (nextCursor *int64)

GetNextCursorFromPageSize computes the next cursor based on the number of objects in the current page, the current cursor, and the page size.

func MarshalCursor

func MarshalCursor[T int64 | string](cursor *CompositeCursor[T]) (string, *framework.Error)

MarshalCursor marshals the cursor into a base64 encoded JSON string. If marshalling fails, an error is returned.

func PaginateObjects

func PaginateObjects[T int64 | string](
	objects []map[string]any,
	pageSize int64,
	cursor *CompositeCursor[T],
) (
	[]map[string]any,
	*T,
	*framework.Error,
)

PaginateObjects implements pagination for APIs that do not support pagination on the server side. It returns a requested page from available records along with a cursor for the next page.

func UpdateNextCursorFromCollectionAPI

func UpdateNextCursorFromCollectionAPI[T int64 | string, Request any](
	ctx context.Context,
	cursor *CompositeCursor[T],
	getPageFunc func(
		ctx context.Context, request *Request,
	) (
		int, string, []map[string]any, *CompositeCursor[T], *framework.Error,
	),
	collectionRequest *Request,
	uniqueIDAttribute string,
) (bool, *framework.Error)

UpdateNextCursorFromCollectionAPI populates the provided cursor in place based on the following rules:

  1. If `cursor.Cursor` is set, we're in the middle of syncing a page of member entity objects for a collection so we should exit early without modifying the cursor.
  2. If `cursor.Cursor` is not set, we need to determine the current collection ID to use. In this case, we'll use the provided `getPageFunc` and `collectionRequest` to request the next collection object. If `cursor.CollectionCursor` is not set we're at the start of a sync so we'll request the first collection object. Otherwise, we'll use the `cursor.CollectionCursor` to request the correct collection object.
  3. If there is a collection object returned, set the `cursor.CollectionID`.
  4. If there is a cursor to the next collection object, we'll save that as `cursor.CollectionCursor`, which will be used to request the next collection object after we process all pages of member objects for the current collection.
  5. If the current collection page does not return any objects, we're done with the current sync and should set `cursor.CollectionID` and `cursor.CollectionCursor` to nil and return.

The provided `getPageFunc` should make a request to the collection API based on the provided `collectionRequest` and parse / return the expected fields. The `collectionRequest` MUST have a page size set to 1, as well as setting any additional params required by the function called in `getPageFunc` to request data from the API.

func ValidateCompositeCursor

func ValidateCompositeCursor[T int64 | string](
	cursor *CompositeCursor[T], entityExternalID string, isMemberEntity bool,
) *framework.Error

ValidateCompositeCursor validates that the composite cursor is correctly set. The following rules are enforced: 1) If the entity is a member entity, then CollectionID must be set. 2) If the entity is not a member entity, then CollectionID and CollectionCursor must be nil.

If no cursor is provided, this returns nil.

Types

type CompositeCursor

type CompositeCursor[T int64 | string] struct {
	// Cursor is the cursor that identifies the first object of the page to return.
	//
	// For datasources where this value is used to populate the query parameter to offset the results in a page,
	// this should have an `int64` type. e.g. the "startAt" parameter in Jira or the "offset" parameter in PagerDuty.
	//
	// For datasources where this contains a request URL, this should have a `string` type.
	Cursor *T `json:"cursor,omitempty"`

	// "Collection" is a generic term for a type of entity that can contain other entities.
	// For example, the "teams" entity in PagerDuty can contain "users". It qualifies as a "Collection".
	// The "group" entity in Jira can contain "users". It qualifies as a "Collection".
	// A collection member entity ID is defined per SoR. For Jira, it is "GroupMember". For PagerDuty, it is "members".
	// The following fields are to ONLY be used when the entity is a member entity, otherwise they must be nil.
	// It is up to the adapter to enforce this rule.
	// CollectionID is the ID of the collection when querying for members.
	// Only used when the entity is a member entity, otherwise it must be nil.
	CollectionID *string `json:"collectionId,omitempty"`

	// CollectionCursor is the cursor that identifies the first collection object of the page to return.
	// Only used when the entity is a member entity, otherwise it must be nil.
	CollectionCursor *T `json:"collectionCursor,omitempty"`
}

CompositeCursor is used to store all required information for pagination. This struct is marshaled into JSON and then base-64 encoded.

func GetNextCursorFromLinkHeader

func GetNextCursorFromLinkHeader(links []string) *CompositeCursor[string]

The Link Header is a comma separated list of links with the following format: <https://test-instance.com/api/v3/repositories/1/issues?per_page=1&page=1>; rel="prev", <https://test-instance.com/api/v3/repositories/1/issues?per_page=1&page=3>; rel="next", <https://test-instance.com/api/v3/repositories/1/issues?per_page=1&page=3>; rel="last", <https://test-instance.com/api/v3/repositories/1/issues?per_page=1&page=1>; rel="first" We want to retrieve the "next" link, or return a nil cursor if it is missing to indicate the end of the sync.

func UnmarshalCursor

func UnmarshalCursor[T int64 | string](cursor string) (*CompositeCursor[T], *framework.Error)

UnmarshalCursor unmarshals the cursor from a base64 encoded JSON string. If unmarshalling fails, an error is returned.

func (*CompositeCursor[T]) ParseOffsetValue

func (c *CompositeCursor[T]) ParseOffsetValue() (int64, *framework.Error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL