The new design uses four separate service functions; List, ListPage, ListRefresh and ListRefreshPage. The first two are used during the initial pagination phase and the latter two are used for any subsequent refresh phases.
71 lines
2.8 KiB
Go
71 lines
2.8 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package target
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/hashicorp/boundary/globals"
|
|
"github.com/hashicorp/boundary/internal/errors"
|
|
"github.com/hashicorp/boundary/internal/listtoken"
|
|
"github.com/hashicorp/boundary/internal/pagination"
|
|
)
|
|
|
|
// ListRefresh lists up to page size targets, filtering out entries that
|
|
// do not pass the filter item function. It will automatically request
|
|
// more targets from the database, at page size chunks, to fill the page.
|
|
// It will start its paging based on the information in the token.
|
|
// It returns a new list token used to continue pagination or refresh items.
|
|
// Targets are ordered by update time descending (most recently updated first).
|
|
// Targets may contain items that were already returned during the initial
|
|
// pagination phase. It also returns a list of any targets deleted since the
|
|
// start of the initial pagination phase or last response.
|
|
func ListRefresh(
|
|
ctx context.Context,
|
|
grantsHash []byte,
|
|
pageSize int,
|
|
filterItemFn pagination.ListFilterFunc[Target],
|
|
tok *listtoken.Token,
|
|
repo *Repository,
|
|
) (*pagination.ListResponse[Target], error) {
|
|
const op = "target.ListRefresh"
|
|
|
|
switch {
|
|
case len(grantsHash) == 0:
|
|
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing grants hash")
|
|
case pageSize < 1:
|
|
return nil, errors.New(ctx, errors.InvalidParameter, op, "page size must be at least 1")
|
|
case filterItemFn == nil:
|
|
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing filter item callback")
|
|
case tok == nil:
|
|
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing token")
|
|
case repo == nil:
|
|
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing repo")
|
|
}
|
|
rt, ok := tok.Subtype.(*listtoken.StartRefreshToken)
|
|
if !ok {
|
|
return nil, errors.New(ctx, errors.InvalidParameter, op, "token did not have a start-refresh token component")
|
|
}
|
|
|
|
listItemsFn := func(ctx context.Context, lastPageItem Target, limit int) ([]Target, time.Time, error) {
|
|
opts := []Option{
|
|
WithLimit(limit),
|
|
}
|
|
if lastPageItem != nil {
|
|
opts = append(opts, WithStartPageAfterItem(lastPageItem))
|
|
}
|
|
// Add the database read timeout to account for any creations missed due to concurrent
|
|
// transactions in the initial pagination phase.
|
|
return repo.listTargetsRefresh(ctx, rt.PreviousPhaseUpperBound.Add(-globals.RefreshReadLookbackDuration), opts...)
|
|
}
|
|
listDeletedIdsFn := func(ctx context.Context, since time.Time) ([]string, time.Time, error) {
|
|
// Add the database read timeout to account for any deletions missed due to concurrent
|
|
// transactions in previous requests.
|
|
return repo.listDeletedIds(ctx, since.Add(-globals.RefreshReadLookbackDuration))
|
|
}
|
|
|
|
return pagination.ListRefresh(ctx, grantsHash, pageSize, filterItemFn, listItemsFn, repo.estimatedCount, listDeletedIdsFn, tok)
|
|
}
|