Page MenuHomePhabricator

D11000.diff
No OneTemporary

D11000.diff

diff --git a/lib/identity-search/identity-search-context.js b/lib/identity-search/identity-search-context.js
--- a/lib/identity-search/identity-search-context.js
+++ b/lib/identity-search/identity-search-context.js
@@ -2,9 +2,13 @@
import invariant from 'invariant';
import * as React from 'react';
+import uuid from 'uuid';
import { identitySearchURL } from '../facts/identity-search.js';
-import { identitySearchHeartbeatTimeout } from '../shared/timeouts.js';
+import {
+ clientRequestVisualTimeout,
+ identitySearchHeartbeatTimeout,
+} from '../shared/timeouts.js';
import type { IdentitySearchAuthMessage } from '../types/identity-search/auth-message-types.js';
import {
type IdentitySearchMessageToClient,
@@ -12,19 +16,42 @@
identitySearchMessageToServerTypes,
identitySearchMessageToClientValidator,
} from '../types/identity-search/messages.js';
+import {
+ type IdentitySearchQuery,
+ type IdentitySearchPrefix,
+} from '../types/identity-search/search-query-types.js';
+import {
+ type IdentitySearchUser,
+ identitySearchResponseValidator,
+} from '../types/identity-search/search-response-types.js';
import type { Heartbeat } from '../types/websocket/heartbeat-types.js';
import { useGetIdentitySearchAuthMessage } from '../utils/identity-search-utils.js';
+import sleep from '../utils/sleep.js';
export type IdentitySearchSocketListener = (
message: IdentitySearchMessageToClient,
) => mixed;
+type PromiseCallbacks = {
+ +resolve: (hits: $ReadOnlyArray<IdentitySearchUser>) => void,
+ +reject: (error: string) => void,
+};
+type Promises = { [queryID: string]: PromiseCallbacks };
+
type IdentitySearchContextType = {
- +addListener: (listener: IdentitySearchSocketListener) => void,
- +removeListener: (listener: IdentitySearchSocketListener) => void,
+ +sendPrefixQuery: (
+ usernamePrefix: string,
+ ) => Promise<$ReadOnlyArray<IdentitySearchUser>>,
+ +addListener: (listener: IdentitySearchSocketListener) => mixed,
+ +removeListener: (listener: IdentitySearchSocketListener) => mixed,
+connected: boolean,
};
+const timeout = async (): Promise<$ReadOnlyArray<IdentitySearchUser>> => {
+ await sleep(clientRequestVisualTimeout);
+ throw new Error('search request timed out');
+};
+
const IdentitySearchContext: React.Context<?IdentitySearchContextType> =
React.createContext<?IdentitySearchContextType>();
@@ -40,6 +67,7 @@
const [identitySearchAuthMessage, setIdentitySearchAuthMessage] =
React.useState<?IdentitySearchAuthMessage>(null);
const socket = React.useRef<?WebSocket>(null);
+ const promises = React.useRef<Promises>({});
const heartbeatTimeoutID = React.useRef<?TimeoutID>();
const previousAuthMessage = React.useRef<?IdentitySearchAuthMessage>(
@@ -148,6 +176,21 @@
message.status.data,
);
}
+ } else if (
+ message.type === identitySearchMessageToClientTypes.SUCCESS ||
+ message.type === identitySearchMessageToClientTypes.ERROR
+ ) {
+ if (!identitySearchResponseValidator.is(message)) {
+ console.log('Invalid search response message');
+ return;
+ }
+ if (message.type === identitySearchMessageToClientTypes.SUCCESS) {
+ promises.current[message.data.id]?.resolve(message.data.hits);
+ delete promises.current[message.data.id];
+ } else {
+ promises.current[message.data.id]?.reject(message.data.error);
+ delete promises.current[message.data.id];
+ }
} else if (
message.type === identitySearchMessageToClientTypes.HEARTBEAT
) {
@@ -166,6 +209,38 @@
stopHeartbeatTimeout,
]);
+ const sendPrefixQuery: (
+ usernamePrefix: string,
+ ) => Promise<$ReadOnlyArray<IdentitySearchUser>> = React.useCallback(
+ (usernamePrefix: string) => {
+ if (!connected || !socket.current) {
+ return Promise.reject(new Error('Socket is not connected'));
+ }
+
+ const queryID = uuid.v4();
+ const prefixQuery: IdentitySearchPrefix = {
+ type: identitySearchMessageToServerTypes.IDENTITY_SEARCH_PREFIX,
+ prefix: usernamePrefix,
+ };
+
+ const searchQuery: IdentitySearchQuery = {
+ type: identitySearchMessageToServerTypes.IDENTITY_SEARCH_QUERY,
+ id: queryID,
+ searchMethod: prefixQuery,
+ };
+
+ const requestPromise: Promise<$ReadOnlyArray<IdentitySearchUser>> =
+ new Promise((resolve, reject) => {
+ promises.current[queryID] = { resolve, reject };
+ });
+
+ socket.current?.send(JSON.stringify(searchQuery));
+
+ return Promise.race([requestPromise, timeout()]);
+ },
+ [connected],
+ );
+
const addListener = React.useCallback(
(listener: IdentitySearchSocketListener) => {
listeners.current.add(listener);
@@ -182,11 +257,12 @@
const value: IdentitySearchContextType = React.useMemo(
() => ({
+ sendPrefixQuery,
connected,
addListener,
removeListener,
}),
- [connected, addListener, removeListener],
+ [connected, addListener, removeListener, sendPrefixQuery],
);
return (

File Metadata

Mime Type
text/plain
Expires
Thu, Dec 19, 3:07 AM (21 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2675126
Default Alt Text
D11000.diff (5 KB)

Event Timeline