Skip to content

Commit

Permalink
bug: fix reload (#36)
Browse files Browse the repository at this point in the history
* bug: fix reload

Before this fix the server was unusable after doing `/reload`,
displaying this error:

```
TypeError: Cannot read property 'size' of undefined
    at app.use (webpack:///./src/server.ts?:22:86)
    at Layer.handle [as handle_request] (webpack:///./node_modules/express/lib/router/layer.js?:95:5)
    at trim_prefix (webpack:///./node_modules/express/lib/router/index.js?:317:13)
    at eval (webpack:///./node_modules/express/lib/router/index.js?:284:7)
    at Function.process_params (webpack:///./node_modules/express/lib/router/index.js?:335:12)
    at next (webpack:///./node_modules/express/lib/router/index.js?:275:10)
    at expressInit (webpack:///./node_modules/express/lib/middleware/init.js?:40:5)
    at Layer.handle [as handle_request] (webpack:///./node_modules/express/lib/router/layer.js?:95:5)
    at trim_prefix (webpack:///./node_modules/express/lib/router/index.js?:317:13)
    at eval (webpack:///./node_modules/express/lib/router/index.js?:284:7)
```

The key problem is that the `/reload` route calls `db.bundleFromEnvironment()`
which is a promise, but it doesn't wait for it to resolve.

I also had to change the bundle reference in all the resolver functions in
`schema.ts` because otherwise after reload if continued serving the old data.
This is because it kept in its scope a reference to the original bundle pointed
at during load time.

* use pure functions
  • Loading branch information
jmelis authored Mar 5, 2019
1 parent 2bca67e commit d6060fc
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 19 deletions.
3 changes: 1 addition & 2 deletions src/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,7 @@ const bundleFromS3 = async(accessKeyId: string, secretAccessKey: string, region:
export const bundleFromDisk = async(path: string) => {
const loadPath = typeof (path) === 'undefined' ? process.env.DATAFILES_FILE : path;
const readFile = util.promisify(fs.readFile);
const contents = String(await readFile(path));

const contents = String(await readFile(loadPath));
return parseBundle(contents);
};

Expand Down
32 changes: 17 additions & 15 deletions src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ const isRef = (obj: Object) : boolean => {

const isNonEmptyArray = (obj: any) => obj.constructor === Array && obj.length > 0;

const resolveSyntheticField = (bundle: db.Bundle,
const resolveSyntheticField = (app: express.Express,
path: string,
schema: string,
subAttr: string) : db.Datafile[] =>
Array.from(bundle.datafiles.filter((datafile) => {
Array.from(app.get('bundle').datafiles.filter((datafile: any) => {

if (datafile.$schema !== schema) { return false; }

if (subAttr in datafile) {
Expand All @@ -42,8 +43,6 @@ export const defaultResolver = (app: express.Express) => (root: any,
args: any,
context: any,
info: any) => {
const bundle = app.get('bundle');

if (info.fieldName === 'schema') return root.$schema;

const val = root[info.fieldName];
Expand All @@ -61,7 +60,7 @@ export const defaultResolver = (app: express.Express) => (root: any,
}

// resolve all the elements of the array
let arrayResolve = val.map((x: db.Referencing) => db.resolveRef(bundle, x));
let arrayResolve = val.map((x: db.Referencing) => db.resolveRef(app.get('bundle'), x));

// `info.returnType` has information about what the GraphQL schema expects
// as a return type. If it starts with `[` it means that we need to return
Expand All @@ -73,13 +72,17 @@ export const defaultResolver = (app: express.Express) => (root: any,
return arrayResolve;
}

if (isRef(val)) return db.resolveRef(bundle, val);
if (isRef(val)) return db.resolveRef(app.get('bundle'), val);
return val;
};

// ------------------ START SCHEMA ------------------

const createSchemaType = (bundle: db.Bundle, schemaTypes: any, interfaceTypes: any, conf: any) => {
const createSchemaType = (app: express.Express,
schemaTypes: any,
interfaceTypes: any,
conf: any) => {

const objTypeConf: any = {};

// name
Expand Down Expand Up @@ -137,7 +140,7 @@ const createSchemaType = (bundle: db.Bundle, schemaTypes: any, interfaceTypes: a
// schema
fieldDef['args'] = { path: { type: GraphQLString } };
fieldDef['resolve'] = (root: any, args: any) => {
return Array.from(bundle.datafiles.filter(
return Array.from(app.get('bundle').datafiles.filter(
(df: db.Datafile) => {
const sameSchema: boolean = df.$schema === fieldInfo.datafileSchema;
return args.path ? df.path === args.path && sameSchema : sameSchema;
Expand All @@ -146,19 +149,18 @@ const createSchemaType = (bundle: db.Bundle, schemaTypes: any, interfaceTypes: a
} else if (fieldInfo.synthetic) {
// synthetic
fieldDef['resolve'] = (root: any) => resolveSyntheticField(
bundle,
app,
root.path,
fieldInfo.synthetic.schema,
fieldInfo.synthetic.subAttr,
);
} else if (fieldInfo.isResource) {
// resource
fieldDef['args'] = { path: { type: GraphQLString } };
fieldDef['resolve'] = (root: any, args: any) => {
return args.path ?
[bundle.resourcefiles.get(args.path)] :
Array.from(bundle.resourcefiles.values());
};
fieldDef['resolve'] = (root: any, args: any) =>
args.path ?
[app.get('bundle').resourcefiles.get(args.path)] :
Array.from(app.get('bundle').resourcefiles.values());
}

// return
Expand Down Expand Up @@ -227,7 +229,7 @@ export const generateAppSchema = (app: express.Express, contents: string) : Grap
const schemaTypes: any = {};
const interfaceTypes: any = {};

schemaData.map((t: any) => createSchemaType(app.get('bundle'), schemaTypes, interfaceTypes, t));
schemaData.map((t: any) => createSchemaType(app, schemaTypes, interfaceTypes, t));

return new GraphQLSchema({
types: Object.values(schemaTypes),
Expand Down
4 changes: 2 additions & 2 deletions src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ export const appFromBundle = async(bundle: Promise<db.Bundle>) => {

server.applyMiddleware({ app });

app.get('/reload', (req: express.Request, res: express.Response) => {
req.app.set('bundle', db.bundleFromEnvironment());
app.get('/reload', async (req: express.Request, res: express.Response) => {
req.app.set('bundle', await db.bundleFromEnvironment());
res.send();
});

Expand Down

0 comments on commit d6060fc

Please sign in to comment.