Page MenuHomePhabricator

D11000.id36880.diff
No OneTemporary

D11000.id36880.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,24 +2,45 @@
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 { AuthMessage } from '../types/identity-search/auth-message-types.js';
import {
type IdentitySearchMessageToClient,
identitySearchMessageToClientTypes,
identitySearchMessageToClientValidator,
} from '../types/identity-search/messages.js';
+import { identitySearchMessageToServerTypes } from '../types/identity-search/messages.js';
+import {
+ type SearchQuery,
+ type Prefix,
+} from '../types/identity-search/search-query-types.js';
+import {
+ type User,
+ searchResponseValidator,
+} from '../types/identity-search/search-response-types.js';
import type { Heartbeat } from '../types/websocket/heartbeat-types.js';
+import sleep from '../utils/sleep.js';
export type IdentitySearchSocketListener = (
message: IdentitySearchMessageToClient,
) => mixed;
+type PromiseCallbacks = {
+ +resolve: (hits: $ReadOnlyArray<User>) => 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<User>>,
+ +addListener: (listener: IdentitySearchSocketListener) => mixed,
+ +removeListener: (listener: IdentitySearchSocketListener) => mixed,
+connected: boolean,
};
@@ -36,6 +57,7 @@
const [connected, setConnected] = React.useState(false);
const listeners = React.useRef<Set<IdentitySearchSocketListener>>(new Set());
const socket = React.useRef<?WebSocket>(null);
+ const promises = React.useRef<Promises>({});
const heartbeatTimeoutID = React.useRef<?TimeoutID>();
const previousAuthMessage = React.useRef<?AuthMessage>(authMessage);
@@ -129,6 +151,20 @@
message.status.data,
);
}
+ } else if (
+ message.type === identitySearchMessageToClientTypes.SUCCESS ||
+ message.type === identitySearchMessageToClientTypes.ERROR
+ ) {
+ if (!searchResponseValidator.is(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
) {
@@ -149,6 +185,43 @@
isSocketActive,
]);
+ const sendPrefixQuery: (
+ usernamePrefix: string,
+ ) => Promise<$ReadOnlyArray<User>> = React.useCallback(
+ (usernamePrefix: string) => {
+ if (!(connected && socket.current)) {
+ return Promise.reject(new Error('Socket is not connected'));
+ }
+
+ const queryID = uuid.v4();
+ const prefixQuery: Prefix = {
+ type: identitySearchMessageToServerTypes.PREFIX,
+ prefix: usernamePrefix,
+ };
+
+ const searchQuery: SearchQuery = {
+ type: identitySearchMessageToServerTypes.SEARCH_QUERY,
+ id: queryID,
+ searchMethod: prefixQuery,
+ };
+
+ const requestPromise: Promise<$ReadOnlyArray<User>> = new Promise(
+ (resolve, reject) => {
+ promises.current[queryID] = { resolve, reject };
+ socket.current?.send(JSON.stringify(searchQuery));
+ },
+ );
+
+ const timeout = async (): Promise<$ReadOnlyArray<User>> => {
+ await sleep(clientRequestVisualTimeout);
+ throw ([]: $ReadOnlyArray<User>);
+ };
+
+ return Promise.race([requestPromise, timeout()]);
+ },
+ [connected],
+ );
+
const addListener = React.useCallback(
(listener: IdentitySearchSocketListener) => {
listeners.current.add(listener);
@@ -165,11 +238,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, 5:17 AM (20 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2675457
Default Alt Text
D11000.id36880.diff (4 KB)

Event Timeline