loopbackio / loopbackio/loopback-next

Support `inq` splitting in `findByForeignKeys`

Ouverte
#3,444 8 commentaires 1 réaction 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

feature needs discussion Relations Repository
Langage dominant
TypeScript
Étoiles
5.1k
Forks
1.1k
Merge moyen
2 j 21 h
PR mergées (30 j)
27

Description

Under the hood, inclusion resolvers are implemented using inq operator:

  1. Gather PK/FK values from source models.
  2. Query target models using inq and PK/FK values from step 1.
  3. Assign target models to navigational property in source models.

This can be problematic when the number of source instances is large, we don't
know if all databases support inq with arbitrary number of items.

To address this issue, LB3 is implementing "inq splitting", where a single query
with arbitrary-sized inq condition is split into multiple queries where each
query has a reasonably-sized inq condition.

Connectors are allowed to specify the maximum inq size supported by the
database via dataSource.settings.inqLimit option. By default, inqLimit is
set to 256.

In this task, we need to improve findByForeignKeys (see https://github.com/strongloop/loopback-next/issues/3443) to handle the maximum size of inq parameter supported by the target database (data-source). When the list of provided FK values is too long, then we should split it into smaller chunks and execute multiple queries.

However, because our Repository interface is generic and does not assume that
a repository has to be backed by a data-source, I am proposing to expose
inqLimit via a new property of the Repository interface instead of accessing
the parameter via DataSource settings.

/**
 * Description of capabilities offered by the connector backing the given
 * datasource.
 */
export interface RepositoryCapabilities {
  /**
   * Maximum number of items allowed for `inq` operators.
   * This value is used to split queries when resolving related models
   * for a large number of source instances.
   */
  inqLimit?: number;
}

To preserve backwards compatibility with existing repository implementation, we
cannot add RepositoryCapabilities directly to the Repository class. We need
to introduce a new interface instead that Repositories can (or may not)
implement.

export interface RepositoryWithCapabilities {
  capabilities: RepositoryCapabilities;
}

See #3387 for more details & a prototype implementation.

Acceptance criteria

To allow the helper to detect inqLimit, we need to extend Repository interfaces.

  • Introduce RepositoryCapabilities interface (called ConnectorCapabilities in the spike), this interface will have a single property inqLimit (for now).
  • Introduce RepositoryWithCapabilities interface (called WithCapabilities in the spike),= this interface should define capabilities property.
  • Implement isRepositoryWithCapabilities type guard
  • Implement getRepositoryCapabilities helper

The rest should be straightforward:

  • Modify findByForeignKeys to obtain inqLimit from repository capabilities and implement query splitting (see the spike implementation).
  • Write unit-level tests where we verify what (and how many) queries are called by findByForeignKeys.
  • Write integration-level tests (in repository-tests) to verify that connectors can handle inqLimit they are advertising. For example, create a test that runs a query returning 1000 records.

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par findByForeignKeys et les interfaces de repository, puis examinez le prototype référencé dans #3387. Suivez la manière dont les capacités du repository sont détectées et inspectez la zone repository-tests avant d’ajouter la couverture unitaire et d’intégration. Le travail est considéré comme terminé lorsque des helpers de capacités existent, que les grandes listes de clés étrangères sont divisées selon inqLimit et que le nombre attendu de requêtes est vérifié.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
typescript
Domaine
backend, testing
Type d'issue
Fonctionnalité
Difficulté
4/5
Temps estimé
3-5 jours
Activité
À l'abandon
Clarté
Plutôt claire
Accessibilité débutants
35/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.