Skip to content

Commit

Permalink
mirror: add typename support to UpdateResults (#1664)
Browse files Browse the repository at this point in the history
Summary:
The internal `UpdateResult` structure now lists IDs of objects whose
typename has been queried. This list is expected to be empty for now.

Test Plan:
Unit tests added.

wchargin-branch: mirror-typename-updateresult
  • Loading branch information
wchargin committed Mar 1, 2020
1 parent 477243f commit 5c937d8
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 12 deletions.
35 changes: 29 additions & 6 deletions src/graphql/mirror.js
Expand Up @@ -735,7 +735,9 @@ export class Mirror {
queryResult: UpdateResult
): void {
for (const topLevelKey of Object.keys(queryResult)) {
if (topLevelKey.startsWith(_FIELD_PREFIXES.OWN_DATA)) {
if (topLevelKey.startsWith(_FIELD_PREFIXES.TYPENAMES)) {
throw new Error("Typename update results not yet supported");
} else if (topLevelKey.startsWith(_FIELD_PREFIXES.OWN_DATA)) {
const rawValue: OwnDataUpdateResult | NodeConnectionsUpdateResult =
queryResult[topLevelKey];
const updateRecord: OwnDataUpdateResult = (rawValue: any);
Expand Down Expand Up @@ -2092,6 +2094,16 @@ type NestedFieldResult = {
+[Schema.Fieldname]: PrimitiveResult | NodeFieldResult,
} | null;
/**
* Result describing only the typename of a set of nodes. Used when we
* only have references to nodes via unfaithful fields.
*/
type TypenamesUpdateResult = $ReadOnlyArray<{|
+__typename: Schema.Typename,
+id: Schema.ObjectId,
|}>;
export type _TypenamesUpdateResult = TypenamesUpdateResult; // for tests
/**
* Result describing own-data for many nodes of a given type. Whether a
* value is a `PrimitiveResult` or a `NodeFieldResult` is determined by
Expand All @@ -2107,6 +2119,7 @@ type OwnDataUpdateResult = $ReadOnlyArray<{
| NodeFieldResult
| NestedFieldResult,
}>;
export type _OwnDataUpdateResult = OwnDataUpdateResult; // for tests
/**
* Result describing new elements for connections on a single node.
Expand All @@ -2117,12 +2130,13 @@ type NodeConnectionsUpdateResult = {
+id: Schema.ObjectId,
+[connectionFieldname: Schema.Fieldname]: ConnectionFieldResult,
};
export type _NodeConnectionsUpdateResult = NodeConnectionsUpdateResult; // for tests
/**
* Result describing both own-data updates and connection updates. Each
* key's prefix determines what type of results the corresponding value
* represents (see constants below). No field prefix is a prefix of
* another, so this characterization is complete.
* Result describing all kinds of updates. Each key's prefix determines
* what type of results the corresponding value represents (see
* constants below). No field prefix is a prefix of another, so this
* characterization is complete.
*
* This type would be exact but for facebook/flow#2977, et al.
*
Expand All @@ -2131,10 +2145,19 @@ type NodeConnectionsUpdateResult = {
type UpdateResult = {
// The prefix of each key determines what type of results the value
// represents. See constants below.
+[string]: OwnDataUpdateResult | NodeConnectionsUpdateResult,
+[string]:
| TypenamesUpdateResult
| OwnDataUpdateResult
| NodeConnectionsUpdateResult,
};
export const _FIELD_PREFIXES = deepFreeze({
/**
* A key of an `UpdateResult` has this prefix if and only if the
* corresponding value represents `TypenamesUpdateResult`s.
*/
TYPENAMES: "typenames_",

/**
* A key of an `UpdateResult` has this prefix if and only if the
* corresponding value represents `OwnDataUpdateResult`s.
Expand Down
28 changes: 22 additions & 6 deletions src/graphql/mirror.test.js
Expand Up @@ -13,6 +13,8 @@ import {
_inTransaction,
_makeSingleUpdateFunction,
Mirror,
type _OwnDataUpdateResult,
type _TypenamesUpdateResult,
} from "./mirror";
import stringify from "json-stable-stringify";

Expand Down Expand Up @@ -799,6 +801,20 @@ describe("graphql/mirror", () => {
}).toThrow('Bad key in query result: "wat_0"');
});

it("throws if given a key with typename results", () => {
const db = new Database(":memory:");
const mirror = new Mirror(db, buildGithubSchema());
const updateId = mirror._createUpdate(new Date(123));
const result = {
typenames_0: ([
{id: "issue:#1", __typename: "Issue"},
]: _TypenamesUpdateResult),
};
expect(() => {
mirror._nontransactionallyUpdateData(updateId, result);
}).toThrow("Typename update results not yet supported");
});

// We test the happy path lightly, because it just delegates to
// other methods, which are themselves tested. This test is
// sufficient to effect full coverage.
Expand All @@ -810,14 +826,14 @@ describe("graphql/mirror", () => {
mirror.registerObject({typename: "Issue", id: "issue:#1"});
mirror.registerObject({typename: "Issue", id: "issue:#2"});
const result = {
owndata_0: [
owndata_0: ([
{
__typename: "Repository",
id: "repo:foo/bar",
url: "url://foo/bar",
},
],
owndata_1: [
]: _OwnDataUpdateResult),
owndata_1: ([
{
__typename: "Issue",
id: "issue:#1",
Expand Down Expand Up @@ -846,7 +862,7 @@ describe("graphql/mirror", () => {
id: "user:alice",
},
},
],
]: _OwnDataUpdateResult),
node_0: {
id: "repo:foo/bar",
issues: {
Expand Down Expand Up @@ -3797,13 +3813,13 @@ describe("graphql/mirror", () => {
const rowid = mirror._logRequest(query, queryParameters, new Date(123));

const response = {
owndata_0: [
owndata_0: ([
{
__typename: "Repository",
id: "repo:foo/bar",
url: "url://foo/bar",
},
],
]: _OwnDataUpdateResult),
};

mirror._logResponse(rowid, response, new Date(456));
Expand Down

0 comments on commit 5c937d8

Please sign in to comment.