-
Notifications
You must be signed in to change notification settings - Fork 865
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: app lazy-loads app-context #2378
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these comments are on code I pushed prior to this PR self review..
@@ -0,0 +1,25 @@ | |||
// @ts-check |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just abstracting this out from src/index.js
await i18n | ||
// @ts-expect-error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addressing some type errors
if (process.env.HOME) { | ||
app.setPath('home', process.env.HOME) | ||
app.setPath('userData', path.join(process.env.HOME, 'data')) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addressing type error (cannot set path to string|undefined)
@@ -47,7 +47,7 @@ | |||
"emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ | |||
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */ | |||
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ | |||
// "outDir": "./", /* Specify an output folder for all emitted files. */ | |||
"outDir": "./dist", /* Specify an output folder for all emitted files. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ran npx -y tsc
and it output a ton of files into src/ that had me scratching my head for a while. I had updated code, but types were still suck to what they were when I ran tsc
. 🙄
@@ -57,7 +58,7 @@ logger.info(`[meta] logs can be found on ${logsPath}`) | |||
|
|||
/** | |||
* | |||
* @param {AnalyticsTimeOptions & import('countly-sdk-nodejs').CountlyAddEventOptions} | |||
* @param {AnalyticsTimeOptions & import('countly-sdk-nodejs').CountlyAddEventOptions} args |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixing error for unnamed parameter
// @ts-ignore | ||
return value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typing is fairly loose in this right now, but resolving that would require updating the entire codebase
e2e tests are passing for me locally now. idk whats going on here. |
tried reverting the daemonReady function.. its passing for me locally again.. lets see if that works on CI |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Took me a while to grasp this, do we need a testing strategy around this? Added a few questions/concerns.
One quick nit (this is not really better in the current release), once ipfs-desktop boots, I have to double click to switch between tabs.
2387-dbl-clk.mov
const originalFnPromise = this.getProp(propertyName) | ||
|
||
return async (...args) => { | ||
const originalFn = await originalFnPromise |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uhm, why have a closure here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To delay the await
until the function is actually called. If we await before it's called then we end up blocking before we need to.
src/context.js
Outdated
this._createDeferredForProp(propertyName) | ||
this._resolvePropForValue(propertyName, value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
overall I think this is abstracting a lot of complex logic and creating a promise(-hell-ish) landscape, I wonder if there's a way to simplify this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hope you feel differently now. This is simplifying things drastically because all you do is set/get properties that may be set/gotten elsewhere. This unblocks a number of things we couldn't do previously, and doesn't require a complete re-write. see #1177 for more information
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, please double-check test/unit/context.spec.js
to confirm that we have enough tests to ensure the core is functioning how we expect.
A logic table for the context class:
|
This is an existing bug: #762 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
another self review
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hope you feel differently now. This is simplifying things drastically because all you do is set/get properties that may be set/gotten elsewhere. This unblocks a number of things we couldn't do previously, and doesn't require a complete re-write. see #1177 for more information
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, please double-check test/unit/context.spec.js
to confirm that we have enough tests to ensure the core is functioning how we expect.
test('can get and call a function before its set', async () => { | ||
let isPending = true | ||
const spy = sinon.spy() | ||
const actualLazyFn = (...args) => { | ||
isPending = false | ||
spy(...args) | ||
} | ||
const lazyFn = ctx.getFn('lazyFn') | ||
const lazyFnCallPromise = lazyFn(123) | ||
expect(isPending).toBe(true) | ||
expect(spy.callCount).toBe(0) | ||
expect(ctx.getProp('lazyFn')).resolves.toBe(actualLazyFn) | ||
ctx.setProp('lazyFn', actualLazyFn) | ||
await lazyFnCallPromise | ||
expect(isPending).toBe(false) | ||
expect(spy.callCount).toBe(1) | ||
expect(spy.getCall(0).args).toEqual([123]) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@whizzzkid this test confirms the lazy function execution works like we expect.
const fn = ctx.getFn('someFnThatMayBeSet_orNot')
await fn() // can be called at any time.. regardless of when we actually set the value.
const cid = await addToIpfs(getFixtures('dir')) | ||
expect(electron.clipboard.writeText.callCount).toEqual(1) | ||
expect(notify.notifyError.callCount).toEqual(0) | ||
expect(notify.notify.callCount).toEqual(1) | ||
expect(cid.toString()).toEqual('bafybeieyzpi3qdqtj7b7hfzdpt2mnmaiicvtrj7ngmf2fc76byecj62gea') | ||
}) | ||
|
||
test('add to ipfs multiple files', async () => { | ||
const cid = await addToIpfs(ctx, getFixtures('dir', 'hello-world.txt')) | ||
const cid = await addToIpfs(getFixtures('dir', 'hello-world.txt')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we no longer need to pass ctx around.
const apiAddress = urlParams.get('api') | ||
if (apiAddress != null) { | ||
window.localStorage.setItem('ipfsApi', apiAddress) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixes console error spotted when testing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
This PR is focused on updating ctx so that it can tolerate extension, updating, and no longer requires specific imports or tribal knowledge to use.
A side-effect of this PR is that the latency of app startup is reduced significantly.
fixes #1177
Benchmarks
Note: nothing else was actively running on my laptop when the "statistical outliers" were detected. It's just that doing things in parallel reduces the chances for outliers to occur because we're doing everything as fast as we can.