Skip to content
This repository has been archived by the owner on Oct 9, 2023. It is now read-only.

add express response.locals object to the job context object #112

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

magicmark
Copy link
Contributor

@magicmark magicmark commented Mar 14, 2018

Addresses #111

Motivation: To be able to pass things from inside getComponent to the rest of the express application (for custom middlewares)

(poked around in test/BatchManager-test.js, but can't see a place we're already asserting things about what is on the context object that we're passing to getComponent)

Thanks!

@goatslacker

@magicmark magicmark force-pushed the add_response_object_to_context branch from 7a6af46 to 25b7921 Compare March 14, 2018 23:23
@magicmark magicmark changed the title add express response object to the job context object add express response.locals object to the job context object Mar 14, 2018
@magicmark magicmark force-pushed the add_response_object_to_context branch from 25b7921 to 8467b13 Compare April 23, 2018 19:58
@magicmark
Copy link
Contributor Author

rebased.

@schleyfox @goatslacker anything I can do to help nudge this along to be merged? Thanks!

@magicmark
Copy link
Contributor Author

magicmark commented May 23, 2018

@schleyfox @goatslacker Rebased again. ping :)

@magicmark magicmark force-pushed the add_response_object_to_context branch from 96b8be7 to 2d96928 Compare May 24, 2018 00:49
@@ -96,6 +96,7 @@ class BatchManager {
duration: null,
html: null,
returnMeta: {},
resLocals: response.locals,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also include request and app level locals?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

specifically, should we just spread baseContext into here?

Copy link
Contributor Author

@magicmark magicmark Jun 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing in request / response sounds good!

Could pass this is in explicitly - spreading in baseContext sounds good too, at the risk of potentially increasing the public api surface area.

I'll update the PR to do this.

(Side note - unclear what batchMeta is used for? Can this be removed?)

╔═ markl@dev21-uswest1cdevc: ~/oss/hypernova git:(add_response_object_to_context)
╚═ ♪ git --no-pager grep batchMeta
src/utils/BatchManager.js:75:      batchMeta: {},

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's being used.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we just spread baseContext into here?

We could change line 147 to be

const context = this.getRequestContext(null, token);

It would be a breaking change but then the context passed in would have access to baseContext as well.

The downside is that the whole response object would be made available which means that consumers may be able to hijack the response.

@goatslacker
Copy link
Collaborator

Motivation: To be able to pass things from inside getComponent to the rest of the express application (for custom middlewares)

What's an example of this? Maybe we can use this to create a test case for the feature.

@magicmark
Copy link
Contributor Author

@goatslacker Thanks for the feedback!

What's an example of this? Maybe we can use this to create a test case for the feature.

We have a few logging middlewares that run at the end of the request. As part of a profiling thing we're doing, we want to include in the log - did the request hit a cold bundle cache or not?

Erring on the side of being overly-verbose, I'll share our sample usage:

So right now, using my forked version, a simplified version of our code looks something like

// (CRS = "component rendering service")

// A home for all the stuff that CRS adds to the response object per component token
type CRSComponentContext = {
    // Did the component request hit a cold cache?
    wasBundleInCache?: boolean,
};

export default async function getComponent(
    requestString: string,
    context: Object,
) {
    context.resLocals.crs = context.resLocals.crs || {};
    const componentContexts = (context.resLocals.crs: { [token: string]: CRSComponentContext });
    componentContexts[context.token] = {};
    const componentContext = componentContexts[context.token];

    // Decode requestString to get bundle/component info
    const componentRequest = getComponentInfo(requestString);

    // Fetch bundle from memory / disk / s3
    const [bundle, wasBundleInCache] = await getBundle(componentRequest.service, componentRequest.sha);

    componentContext.wasBundleInCache = wasBundleInCache;

    const component = bundle.default[componentRequest.name];

    return component;
}

This allows us in a middleware later on to access res.locals.crs[key]; and get arbitrary information about that specific component request.

(For example, somewhere else, in a logging middleware, we do something like)

// (uses https://www.npmjs.com/package/tweenz)
export default function AccessLog () {
    return async (requestDetails, req, res) => {
        // wait for request to complete
        await requestDetails;

        const componentRequests = Object.keys(hypernovaRequest).map(key => {
            const componentContext = res.locals.crs[key];
            return {
                // we'd also actually log some other stuff here too like timing, status etc
                ...componentContext,
            }
        });

        logSomewhere(componentRequests);
    };
};

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants