Description
New Issue Checklist
- I am not disclosing a vulnerability.
- I am not just asking a question.
- I have searched through existing issues.
- I can reproduce the issue with the latest version of Parse Server.
Issue Description
Currently, all ParseServer
initialization is done in the constructor
and there is no way to ensure everything is ready before the app is loaded.
The main issue(s)
-
Parse Server constructor will continue to do initialization tasks long after the constructor caller returns, and we have no way to await for its completion.
-
Server will start to listen to incoming http requests before CloudCode is loaded.
This can be bad in some case because express
and ParseServer
can get exposed to the world, before it have completed its initialization leading to client side errors
Ideally, we should refactor the constructor
startup process into a async start()
method that can be awaited on.
Currently we see at occasion during rolling updates clients running cloud functions Parse.Cloud.run('xyz')
and receiving Parse.Error
Function XYZ does not exists
. This is caused by having the parse api
mounted and express
running before all Cloud Code have a time to start.
A few solutions
(A) Without introducing a BC Break
This solution is great as a compromise for now.. It's simple, and have no long term implications.
Add a isReady()
function that return a promise that is resolved when the constructor has completed
class ParseServer {
private isReady : Promise<void>
constructor(){
this.isReady = new Promise<void>(resolve => {
// ... ALL CURRENT CONSTRUCTOR CODE
})
}
public function isReady () : Promise<void> {
return this.isReady;
}
}
// ...... server.ts
const api = new ParseServer(config)
await api.ready()
(B) Without introducing a BC Break, and a path forward
This solution is great long term solution.
Move constructor init into a start()
method, and add a ParseServerOption
autoStart: true
. Later in version 6.0.0
we can default autoStart
to false
or ignore/deprecate the parameter
class ParseServer {
constructor(options){
if(options.autoStart === true){
this.start()
}
}
public function start() : Promise<void> {
// ... ALL CURRENT CONSTRUCTOR CODE ...
}
}
// ...... server.ts
const config = { autoStart : false };
const api = new ParseServer(config)
await api.start()
(C) Pure and simple BC Break
Just put all constructor code into a start()
and tell users they need to call it in the 5.0.0
release notes
const api = new ParseServer(config)
await api.start()
(C) is obvisously a bit harsh 😆 ! LMK what you think and i can submit a PR for either (A) or (B)
Steps to reproduce
Actual Outcome
Expected Outcome
Failing Test Case / Pull Request
- 🤩 I submitted a PR with a fix and a test case.
- 🧐 I submitted a PR with a failing test case.
Environment
Server
- Parse Server version: 4.5.0
- Operating system: linux/windows
- Local or remote host (AWS, Azure, Google Cloud, Heroku, Digital Ocean, etc): local a d GC
Database
- System (MongoDB or Postgres):
mingo
- Database version:
recent
- Local or remote host (MongoDB Atlas, mLab, AWS, Azure, Google Cloud, etc):
gc
Client
- SDK (iOS, Android, JavaScript, PHP, Unity, etc):
js
- SDK version:
4.5.4
Logs
Have a good day,
Samuel