Skip to content
This repository has been archived by the owner on May 21, 2020. It is now read-only.

Improve demo, simplify user experience #20

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open

Conversation

rylandg
Copy link
Contributor

@rylandg rylandg commented Dec 15, 2018

I know this is a big PR and I apologize for that. These are changes that accumulated during kubecon and while I was flying. It really adds to the demo and enables some even better changes down the road. I'm going to list the changes at a high level here.

  1. It's now possible to run against a local express server. Deploying with all of these dependencies became very cumbersome so it's very nice to have.
  2. I've split up the repo into logical directories. This allows us to shard our npm dependencies which SUBSTANTIALLY reduced deploy times. You can now redeploy the backend function in 5-6 seconds and the frontend function in ~15 seconds.
  3. I've also added a number of npm scripts that saves time when a new user is running the demo.
  4. I've added custom textures which are served from the servePage endpoint. This improves the visual appeal of the demo and is the first step to making it look like real terrain.
  5. Because sandbox has 1 concurrency by default, simply fetching resources from the HTML was causing 429 errors. I now force assets to load serially and added a sleep when scaling Workers.
  6. I've completely removed the need for a user to supply custom endpoints of any type. As long as they've used bn login the demo will work
  7. Terrain is now chunked vertically in addition to horizontally. This has a negative effect on client performance currently, but there are ways we can reduce that overhead. Regardless, it's worth it for the much more appealing terrain.

Although I thought it would be too difficult to split the patches I put a lot of effort into isolating the commits. The changes are far less overwhelming when you look at a commit by commit basis.

This PR also needs binaris/binaris#418 to function

Copy link

@vogre vogre left a comment

Choose a reason for hiding this comment

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

I didn't understand why there was need for binaris/binaris#418 (and subsequent binaris/binaris#419), what CORS broke?

}

async function getPublicPath(accountID, endpoint) {
process.env.BINARIS_INVOKE_ENDPOINT = endpoint;
Copy link

Choose a reason for hiding this comment

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

Is overriding process.env.BINARIS_INVOKE_ENDPOINT before storing it in savedEndpoint a bug?

Also, this assumes that binaris/sdk/url behaves in a certain way - if you need a specific functionality from the SDK maybe this function should be in the SDK?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  1. It's not a bug. Our SDK relies on Environment variables and cannot be overridden with passed values. I definitely agree this could prompt a change but that could entail a lengthy discussion. How about we do that in parallel?
  2. It does assume but the alternative is exposing bloat to the user. For now I'm ok with this hack until we fix the underlying issues

Copy link

Choose a reason for hiding this comment

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

Do we still need this whole function with the sandbox shutdown?

Copy link
Contributor Author

@rylandg rylandg left a comment

Choose a reason for hiding this comment

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

@vogre it broke because instead of the user supplying the endpoint for the function it's automatically generated using our internal SDK logic. As of now our SDK does not use the same endpoint that we print to the user. Therefore them pasting it in the browser forces a redirect and therefore CORS.

}

async function getPublicPath(accountID, endpoint) {
process.env.BINARIS_INVOKE_ENDPOINT = endpoint;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

  1. It's not a bug. Our SDK relies on Environment variables and cannot be overridden with passed values. I definitely agree this could prompt a change but that could entail a lengthy discussion. How about we do that in parallel?
  2. It does assume but the alternative is exposing bloat to the user. For now I'm ok with this hack until we fix the underlying issues

@vogre
Copy link

vogre commented Dec 17, 2018

  1. it looks like a bug. If I do
a = newValue;
oldValue = a;
a = oldValue;

then the last two lines have no effect.

  1. The SDK uses environment variables in our environment: https://github.com/binaris/realms/pull/68/files - when running in a Binaris function it has the correct values.

From your use-case it looks like you are trying to use the SDK for building your code to run in multiple realms (sandbox, prod) and the assumption during binaris/binaris#392 was that SDK is for use in Binaris functions and not for build systems -- if this is wrong we need to fix the SDK - the current suggested change will break if the SDK internals change in any way (and this means we are not allowed to change them?).

As a quick fix that does not entail a lengthy discussion, which may also be practical for users: how about we serve the HTML templated from the function instead of doing replace-in-file during the build stage? Most web frameworks support templating, and our examples can also demonstrate it.

@rylandg
Copy link
Contributor Author

rylandg commented Dec 17, 2018

  1. I was 100% wrong, that is a bug and I'll fix it. Sorry for not realizing it immediately.
  2. (Regarding SDK) Indeed I'm using for build. I agree it's crappy but the alternative puts more burden on the user. I'm trying to minimize the overhead of using/running this demo as much as possible. I 100% believe we need to not only fix but separate out the SDK.
  3. I'm not sure I 100% follow. I want to avoid more complex templating solutions because I'm doing a very basic sed and adding more bloat and abstraction will increase the barrier of entry for users. I think you're suggesting that we deploy with the HTML template and then at invocation time inject the accountID into the HTML before serving. Is accountID available in runtime?

@vogre
Copy link

vogre commented Dec 17, 2018

Is accountID available in runtime?

Good question - this was discussed but somehow missed - I've opened PRs for spec and implementation.

I want to avoid more complex templating solutions because I'm doing a very basic sed

In my opinion sed is confusing and I wouldn't recommend users to build their examples with a build process that requires replacing text in files, and templating is familiar if you used Jinja2 or ERB or any other templating solution.

It would add about 10 lines of code to our demo web-server servePage.js, but will be useful for examples.

@rylandg
Copy link
Contributor Author

rylandg commented Dec 17, 2018

Once we have accountID available in the function I will happily switch the implementation.

Alternatively I can add BINARIS_ACCOUNT_ID as a env var in binaris.yml and then programmatically inject it during backend function deployment.

Thoughts?

@vogre
Copy link

vogre commented Dec 17, 2018

I think it's preferrable to wait for account ID in the function to avoid changing the example twice.

@rylandg
Copy link
Contributor Author

rylandg commented Dec 17, 2018

I have no issue with that but it means the PR might grow more. I've been spending my free time improving this example.

@vogre
Copy link

vogre commented Dec 19, 2018

BINARIS_ACCOUNT_ID is now available in environment

@rylandg
Copy link
Contributor Author

rylandg commented Dec 19, 2018

@vogre Awesome, will update.

@rylandg
Copy link
Contributor Author

rylandg commented Jan 2, 2019

@vogre I made the improvements we discussed and you helped me with. We now use dot for simple templating. I'm also considering splitting the servePage function into a completely different "app" and then depending on it from this one.

@vogre
Copy link

vogre commented Jan 3, 2019

@rylandg the last change looks good, do you want me to review the whole PR now?

@rylandg
Copy link
Contributor Author

rylandg commented Jan 3, 2019

@vogre that would be great

Copy link

@vogre vogre left a comment

Choose a reason for hiding this comment

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

Thanks!

I've left a few comments, mostly requests to revisit since this was done for sandbox and now in public beta perhaps not needed.

I'd really prefer the getPublicPath function to not do the environment variables manipulation so that users don't copy it, is was done in the first place because of sandbox IIUC, the only major request is to update it before merge.

const genStartTime = process.hrtime();

const { blockCount, data, maxHeight } = noiseGen(
parseInt(xPos, 10), parseInt(yPos, 10),
Copy link

Choose a reason for hiding this comment

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

I think it would be cleaner to have all string->int conversion in the beginning of the handler, (even if some arguments are now passed as strings (numTex, downscale) they work due to conversion, but it's not optimal).

if (maxHeight % size !== 0) {
maxHeight = Math.ceil(maxHeight / size) * size;

if ((minHeight) > (cY + size)) {
Copy link

Choose a reason for hiding this comment

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

Nit: extra parentheses?

const game = setupDemo();

game.animate();
Promise.resolve(setupDemo()).then((game) => {
Copy link

Choose a reason for hiding this comment

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

Can be setupDemo().then((game) => { ?

}

void main() {
vec4 lights = vec4(0.0, 0.0, 0.0, 1.0);
Copy link

Choose a reason for hiding this comment

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

Nit: mixed tabs and spaces.


void main() {
vUv = uv;
vNormal = (modelMatrix * vec4(normal, 0.0)).xyz;
Copy link

Choose a reason for hiding this comment

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

Nit: mixed tabs and spaces.

headers = makeHeaders(blockCount, maxHeight, respBody.length, genDataTimeStr);
statusCode = 200;
}
if (ctx.request.query.express_server) {
Copy link

Choose a reason for hiding this comment

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

What do you think about instead of adding a fake express_server, pass a HTTPResponse constructor and move this to express?

const genStr = (failedGenTime[0] * 1000) + (failedGenTime[1] / 1000000);
headers = makeHeaders(blockCount, maxHeight, 0, genStr);
respBody = new Buffer(2);
statusCode = 200;
Copy link

Choose a reason for hiding this comment

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

Code-style: my preference would be to have an early-return here (but would require moving into a separate function).

@@ -15,14 +17,21 @@ exports.handler = async (body, ctx) => {
resourcePath = '/index.html';
}

const webpage = await fs.readFile(`${prefix}${resourcePath}`);
let webPage;
Copy link

Choose a reason for hiding this comment

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

Since this code is mostly shared with react-serverless, perhaps also rename to webResource.

Also if this is to be a recommended code for using in a Binaris function perhaps makes senses moving it into a unified place.

}

async function getPublicPath(accountID, endpoint) {
process.env.BINARIS_INVOKE_ENDPOINT = endpoint;
Copy link

Choose a reason for hiding this comment

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

Do we still need this whole function with the sandbox shutdown?

}
const accountID = await getAccountId(undefined);
const FRACTAL_ENDPOINT = await getFractalURL(accountID);
const PUBLIC_PATH = (await getPublicPath(accountID, ' ')).slice(8);
Copy link

Choose a reason for hiding this comment

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

Why do we slice(8) the https:// away for webpack? Can we get it through a URL object instead?

@michaeladda
Copy link
Contributor

@rylandg any update on this?

@rylandg
Copy link
Contributor Author

rylandg commented Feb 25, 2019

@michaeladda

Yes. It's a complex set of fixes and I've just been prioritizing other things. I viewed this as overall lower importance considering that the example already works and these are just further features/improvements.

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