<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @emails oncall+relay
 * @flow strict-local
 * @format
 */

// flowlint ambiguous-object-type:error

'use strict';

const {
  createOperationDescriptor,
  getRequest,
  getRequestIdentifier,
  Observable,
  PreloadableQueryRegistry,
  RelayFeatureFlags,
  ReplaySubject,
} = require('relay-runtime');

import type {
  PreloadableConcreteRequest,
  PreloadedQueryInner_DEPRECATED,
  PreloadFetchPolicy,
  PreloadOptions,
  PreloadQueryStatus,
  VariablesOf,
} from './EntryPointTypes.flow';
import type {
  ConcreteRequest,
  GraphQLResponse,
  GraphQLTaggedNode,
  IEnvironment,
  OperationType,
  Subscription,
} from 'relay-runtime';

// Expire results by this delay after they resolve.
const DEFAULT_PREFETCH_TIMEOUT = 30 * 1000; // 30 seconds

const WEAKMAP_SUPPORTED = typeof WeakMap === 'function';
const STORE_OR_NETWORK_DEFAULT: PreloadFetchPolicy = 'store-or-network';

const pendingQueriesByEnvironment = WEAKMAP_SUPPORTED
  ? new WeakMap()
  : new Map();

type PendingQueryEntry =
  | $ReadOnly<{|
      cacheKey: string,
      fetchKey: ?string | ?number,
      fetchPolicy: PreloadFetchPolicy,
      kind: 'network',
      id: ?string,
      name: string,
      status: PreloadQueryStatus,
      subject: ReplaySubject<GraphQLResponse>,
      subscription: Subscription,
    |}>
  | $ReadOnly<{|
      cacheKey: string,
      fetchKey: ?string | ?number,
      fetchPolicy: PreloadFetchPolicy,
      kind: 'cache',
      id: ?string,
      name: string,
      status: PreloadQueryStatus,
    |}>;

function preloadQuery<TQuery: OperationType, TEnvironmentProviderOptions>(
  environment: IEnvironment,
  preloadableRequest: GraphQLTaggedNode | PreloadableConcreteRequest<TQuery>,
  variables: VariablesOf<TQuery>,
  options?: ?PreloadOptions,
  environmentProviderOptions?: ?TEnvironmentProviderOptions,
): PreloadedQueryInner_DEPRECATED<TQuery, TEnvironmentProviderOptions> {
  let _pendingQueries = pendingQueriesByEnvironment.get(environment);
  if (_pendingQueries == null) {
    _pendingQueries = new Map();
    pendingQueriesByEnvironment.set(environment, _pendingQueries);
  }
  const pendingQueries: Map<string, PendingQueryEntry> = _pendingQueries; // store in a const for flow
  const queryEntry = preloadQueryDeduped(
    environment,
    pendingQueries,
    preloadableRequest,
    variables,
    options,
  );
  const source =
    queryEntry.kind === 'network'
      ? Observable.create(sink => {
          let subscription;
          if (pendingQueries.get(queryEntry.cacheKey) == null) {
            const newQueryEntry = preloadQueryDeduped(
              environment,
              pendingQueries,
              preloadableRequest,
              variables,
              options,
            );
            if (newQueryEntry.kind === 'network') {
              subscription = newQueryEntry.subject.subscribe(sink);
            }
          } else {
            subscription = queryEntry.subject.subscribe(sink);
          }
          return () => {
            subscription?.unsubscribe();
            if (
              RelayFeatureFlags.DELAY_CLEANUP_OF_PENDING_PRELOAD_QUERIES ===
              true
            ) {
              setTimeout(() => {
                // Clear the cache entry after the default timeout
                // null-check for Flow
                if (queryEntry != null) {
                  cleanup(pendingQueries, queryEntry);
                }
              }, DEFAULT_PREFETCH_TIMEOUT);
            } else {
              cleanup(pendingQueries, queryEntry);
            }
          };
        })<commit_msg>Don't cleanup pending preload queries when you're server rendering<commit_after>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @emails oncall+relay
 * @flow strict-local
 * @format
 */

// flowlint ambiguous-object-type:error

'use strict';

const {
  createOperationDescriptor,
  getRequest,
  getRequestIdentifier,
  Observable,
  PreloadableQueryRegistry,
  RelayFeatureFlags,
  ReplaySubject,
} = require('relay-runtime');

import type {
  PreloadableConcreteRequest,
  PreloadedQueryInner_DEPRECATED,
  PreloadFetchPolicy,
  PreloadOptions,
  PreloadQueryStatus,
  VariablesOf,
} from './EntryPointTypes.flow';
import type {
  ConcreteRequest,
  GraphQLResponse,
  GraphQLTaggedNode,
  IEnvironment,
  OperationType,
  Subscription,
} from 'relay-runtime';

// Expire results by this delay after they resolve.
const DEFAULT_PREFETCH_TIMEOUT = 30 * 1000; // 30 seconds

const WEAKMAP_SUPPORTED = typeof WeakMap === 'function';
const STORE_OR_NETWORK_DEFAULT: PreloadFetchPolicy = 'store-or-network';

const pendingQueriesByEnvironment = WEAKMAP_SUPPORTED
  ? new WeakMap()
  : new Map();

type PendingQueryEntry =
  | $ReadOnly<{|
      cacheKey: string,
      fetchKey: ?string | ?number,
      fetchPolicy: PreloadFetchPolicy,
      kind: 'network',
      id: ?string,
      name: string,
      status: PreloadQueryStatus,
      subject: ReplaySubject<GraphQLResponse>,
      subscription: Subscription,
    |}>
  | $ReadOnly<{|
      cacheKey: string,
      fetchKey: ?string | ?number,
      fetchPolicy: PreloadFetchPolicy,
      kind: 'cache',
      id: ?string,
      name: string,
      status: PreloadQueryStatus,
    |}>;

function preloadQuery<TQuery: OperationType, TEnvironmentProviderOptions>(
  environment: IEnvironment,
  preloadableRequest: GraphQLTaggedNode | PreloadableConcreteRequest<TQuery>,
  variables: VariablesOf<TQuery>,
  options?: ?PreloadOptions,
  environmentProviderOptions?: ?TEnvironmentProviderOptions,
): PreloadedQueryInner_DEPRECATED<TQuery, TEnvironmentProviderOptions> {
  let _pendingQueries = pendingQueriesByEnvironment.get(environment);
  if (_pendingQueries == null) {
    _pendingQueries = new Map();
    pendingQueriesByEnvironment.set(environment, _pendingQueries);
  }
  const pendingQueries: Map<string, PendingQueryEntry> = _pendingQueries; // store in a const for flow
  const queryEntry = preloadQueryDeduped(
    environment,
    pendingQueries,
    preloadableRequest,
    variables,
    options,
  );
  const source =
    queryEntry.kind === 'network'
      ? Observable.create(sink => {
          let subscription;
          if (pendingQueries.get(queryEntry.cacheKey) == null) {
            const newQueryEntry = preloadQueryDeduped(
              environment,
              pendingQueries,
              preloadableRequest,
              variables,
              options,
            );
            if (newQueryEntry.kind === 'network') {
              subscription = newQueryEntry.subject.subscribe(sink);
            }
          } else {
            subscription = queryEntry.subject.subscribe(sink);
          }
          return () => {
            subscription?.unsubscribe();
            if (environment.isServer()) {
              return;
            }
            if (
              RelayFeatureFlags.DELAY_CLEANUP_OF_PENDING_PRELOAD_QUERIES ===
              true
            ) {
              setTimeout(() => {
                // Clear the cache entry after the default timeout
                // null-check for Flow
                if (queryEntry != null) {
                  cleanup(pendingQueries, queryEntry);
                }
              }, DEFAULT_PREFETCH_TIMEOUT);
            } else {
              cleanup(pendingQueries, queryEntry);
            }
          };
        })
{'fraction_non_alphanumeric': 0.09198697068403909, 'fraction_numerical': 0.002084690553745928, 'mean_word_length': 2.692159692159692, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7657998', 'n_tokens_mistral': 2149, 'n_tokens_neox': 2126, 'n_words': 481}