Skip to content

Parse Server may expose HTTP routes before complete initialization #7527

Closed
@sadortun

Description

@sadortun

New Issue Checklist

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    block:majorNeeds to be resolved before next major release; remove label afterwardsstate:breakingBreaking change requires major version increment and `BREAKING CHANGE` commit messagestate:releasedReleased as stable versionstate:released-alphaReleased as alpha versionstate:released-betaReleased as beta versiontype:bugImpaired feature or lacking behavior that is likely assumed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions