Skip to content

Commit

Permalink
feat: Include version in startup message (#615) Thanks to jcw-!
Browse files Browse the repository at this point in the history
* feat: Include version in startup message

* Add version to startup message

* Add version to CubejsServer

* Add version to CubejsServerCore

* Make version available in return of listen

* Use version returned from listen

* Make version an immutable static method

* Update docs with how to use version

* Update doc examples to log version

* Update examples to log version

* Update guides to log version

* Update TypeScript type to include version
  • Loading branch information
jcw- authored Apr 30, 2020
1 parent 23da279 commit d2f1732
Show file tree
Hide file tree
Showing 23 changed files with 156 additions and 132 deletions.
15 changes: 12 additions & 3 deletions docs/Cube.js-Backend/@cubejs-backend-server-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,6 @@ CubejsServerCore.create({
})
```


### contextToAppId

It is a [Multitenancy Setup](multitenancy-setup) option.
Expand Down Expand Up @@ -319,7 +318,7 @@ It is usually used in [Multitenancy Setup](multitenancy-setup).

### schemaVersion

Schema version can be used to tell Cube.js schema should be recompiled in case schema code depends on dynamic definitions fetched from some external database or API.
Schema version can be used to tell Cube.js schema should be recompiled in case schema code depends on dynamic definitions fetched from some external database or API.
This method is called on each request however `RequestContext` parameter is reused per application id returned by [contextToAppId](#options-reference-context-to-app-id).
If returned string has been changed, schema will be recompiled.
It can be used in both multitenant and single tenant environments.
Expand Down Expand Up @@ -369,7 +368,7 @@ Providing `updateCompilerCacheKeepAlive: true` keeps frequently used schemas in

### allowUngroupedWithoutPrimaryKey

Providing `allowUngroupedWithoutPrimaryKey: true` disables primary key inclusion check for `ungrouped` queries.
Providing `allowUngroupedWithoutPrimaryKey: true` disables primary key inclusion check for `ungrouped` queries.

### telemetry

Expand Down Expand Up @@ -455,3 +454,13 @@ CubejsServerCore.create({
repositoryFactory: ({authInfo}) => new ApiFileRepository()
});
```

## Version

`CubejsServerCore.version` is a method that returns the semantic package version of `@cubejs-backend/server`.

```javascript
const CubejsServerCore = require('@cubejs-backend/server-core');

console.log(CubejsServerCore.version());
```
22 changes: 17 additions & 5 deletions docs/Cube.js-Backend/@cubejs-backend-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,37 @@ Creates an instance of `CubejsServer`.

You can set server port using `PORT` environment variable. Default port is `4000`.

### Example
#### Example

```javascript
const CubejsServer = require('@cubejs-backend/server');

const server = new CubejsServer();

server.listen().then(({ port }) => {
console.log(`πŸš€ Cube.js server is listening on ${port}`);
server.listen().then(({ version, port }) => {
console.log(`πŸš€ Cube.js server (${version}) is listening on ${port}`);
});
```

### CubejsServer.version()

`CubejsServer.version` is a method that returns the semantic package version of `@cubejs-backend/server`.

```javascript
const CubejsServer = require('@cubejs-backend/server');

console.log(CubejsServer.version());
```

### this.listen([options])

Instantiates the Express.js App to listen to the specified `PORT`. Returns a promise that resolves with the following members:

* `port {number}` The port at which CubejsServer is listening for insecure connections for redirection to HTTPS, as specified by the environment variable `PORT`. Defaults to 4000.
* `tlsPort {number}` If TLS is enabled, the port at which CubejsServer is listening for secure connections, as specified by the environment variable `TLS_PORT`. Defaults to 4433.
* `app {Express.Application}` The express App powering CubejsServer
* `server {http.Server}` The `http` Server instance. If TLS is enabled, returns a `https.Server` instance instead.
* `version {string}` The semantic package version of `@cubejs-backend/server`

Cube.js can also support TLS encryption. See the [Security page on how to enable tls](security#enabling-tls) for more information.

Expand All @@ -50,8 +62,8 @@ const { createTerminus } = require('@godaddy/terminus');

const cubejsServer = new CubejsServer();

cubejsServer.listen().then(({ port, server }) => {
console.log(`πŸš€ Cube.js server is listening on ${port}`);
cubejsServer.listen().then(({ version, port, server }) => {
console.log(`πŸš€ Cube.js server (${version}) is listening on ${port}`);

createTerminus(server, {
healthChecks: {
Expand Down
28 changes: 14 additions & 14 deletions docs/Cube.js-Backend/Caching.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ The second in-database level is called **pre-aggregations** and requires explici
Cube.js caches the results of executed queries using in-memory cache. The cache
key is generated SQL with any existing query dependent pre-aggregations.

Upon incoming request Cube.js first checks the cache using this key.
Upon incoming request Cube.js first checks the cache using this key.
If nothing is found it executes the query in database, returns result back alongside writing to the cache.
Since 0.15.0 in case there's an existing value in cache it will be returned only if `refreshKey` value for query isn't changed.
Otherwise [query renewal](#in-memory-cache-force-query-renewal) will be performed.
Expand All @@ -33,12 +33,12 @@ So, Cube.js defines a `refreshKey` for each cube. [refreshKeys](cube#parameters-

__Note__: Cube.js *also caches* the results of `refreshKeys` for a fixed time interval in order to avoid issuing them too often. If you need Cube.js to immediately respond to changes in data, see the [Force Query Renewal](#in-memory-cache-force-query-renewal) section.

When a query's result needs to be refreshed, Cube.js will re-execute the query in the foreground and repopulate the cache.
This means that cached results may still be served to users requesting them while `refreshKey` values aren't changed from Cube.js perspective.
When a query's result needs to be refreshed, Cube.js will re-execute the query in the foreground and repopulate the cache.
This means that cached results may still be served to users requesting them while `refreshKey` values aren't changed from Cube.js perspective.
The cache entry will be refreshed in the foreground if one of the two following conditions is met:

- Query cache entry is expired. The default expiration time is 6 hours for cubes with default `refreshKey` and 24 hours where it was set.
- The result of the `refreshKey` SQL query is different from the previous one. At this stage `refreshKey` won't be refreshed in foreground if it's available in cache.
- The result of the `refreshKey` SQL query is different from the previous one. At this stage `refreshKey` won't be refreshed in foreground if it's available in cache.

### Refresh Key Implementation

Expand All @@ -57,8 +57,8 @@ You can set up a custom refresh check SQL by changing [refreshKey](cube#paramete

In these instances, Cube.js needs a query crafted to detect updates to the rows that power the cubes. Often, a `MAX(updated_at_timestamp)` for OLTP data will accomplish this, or examining a metadata table for whatever system is managing the data to see when it last ran.

Note that the result of `refreshKey` query itself is cached for 10 seconds for RDBMS backends and for 2 minutes for big data backends by default.
You can change it by passing [refreshKey every](cube#parameters-refresh-key) parameter.
Note that the result of `refreshKey` query itself is cached for 10 seconds for RDBMS backends and for 2 minutes for big data backends by default.
You can change it by passing [refreshKey every](cube#parameters-refresh-key) parameter.
This cache is useful so that Cube.js can build query result cache keys without issuing database queries and respond to cached requests very quickly.

### Force Query Renewal
Expand All @@ -75,8 +75,8 @@ If you need to force a specific query to load fresh data from the database (if i

The `renewQuery` option applies to the `refreshKey` caching system mentioned above, *not* the actual query result cache. If `renewQuery` is passed, Cube.js will always re-execute the `refreshKey` query, skipping that layer of caching, but, if the result of the `refreshKey` query is the same as the last time it ran, that indicates any current query result cache entries are valid, and they will be served. This means that cached data may still be served by Cube.js even if `renewQuery` is passed. This is a good thing: if the underlying data hasn't changed, the expensive query doesn't need to be re-run, and the database doesn't have to work as hard. This does mean that the `refreshKey` SQL must accurately report data freshness for the `renewQuery` to actually work and renew the query.

For situations like real-time analytics or responding to live user changes to underlying data, the `refreshKey` query cache can prevent fresh data from showing up immediately.
For these situations, you can mostly disable the `refreshKey` cache by setting the [refreshKey every](cube#parameters-refresh-key) parameter to something very low, like `1 second`.
For situations like real-time analytics or responding to live user changes to underlying data, the `refreshKey` query cache can prevent fresh data from showing up immediately.
For these situations, you can mostly disable the `refreshKey` cache by setting the [refreshKey every](cube#parameters-refresh-key) parameter to something very low, like `1 second`.
This means Cube.js will always check the data freshness before executing a query, and notice any changed data underneath.

## Pre-Aggregations
Expand All @@ -100,7 +100,7 @@ reference.](pre-aggregations)
```javascript
cube(`Orders`, {
// ...

preAggregations: {
amountByCreated: {
type: `rollup`,
Expand All @@ -113,7 +113,7 @@ cube(`Orders`, {
```

### Refresh Strategy

Refresh strategy can be customized by setting the [refreshKey](pre-aggregations#refresh-key) property for the pre-aggregation.

The default value of the `refreshKey` is the same as for cube that defines pre-aggregation.
Expand All @@ -123,7 +123,7 @@ It can be redefined either by providing SQL
```javascript
cube(`Orders`, {
// ...

preAggregations: {
amountByCreated: {
type: `rollup`,
Expand All @@ -143,7 +143,7 @@ or by providing refresh time interval
```javascript
cube(`Orders`, {
// ...

preAggregations: {
amountByCreated: {
type: `rollup`,
Expand Down Expand Up @@ -183,8 +183,8 @@ const server = new CubejsServer();

setInterval(() => server.runScheduledRefresh(), 5000);

server.listen().then(({ port }) => {
console.log(`πŸš€ Cube.js server is listening on ${port}`);
server.listen().then(({ version, port }) => {
console.log(`πŸš€ Cube.js server (${version}) is listening on ${port}`);
}).catch(e => {
console.error('Fatal error during server start: ');
console.error(e.stack || e);
Expand Down
20 changes: 9 additions & 11 deletions docs/Cube.js-Backend/Deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ Below you can find guides for popular deployment environments:

## Production Mode

When running Cube.js Backend in production make sure `NODE_ENV` is set to `production`.
When running Cube.js Backend in production make sure `NODE_ENV` is set to `production`.
Such platforms, such as Heroku, do it by default.
In this mode Cube.js unsecured development server and Playground will be disabled by default because there's a security risk serving those in production environments.
Production Cube.js servers can be accessed only with [REST API](rest-api) and Cube.js frontend libraries.
Production Cube.js servers can be accessed only with [REST API](rest-api) and Cube.js frontend libraries.

### Redis

Also, Cube.js requires [Redis](https://redis.io/), in-memory data structure store, to run in production.
It uses Redis for query caching and queue.
Set `REDIS_URL` environment variable to provide Cube.js with Redis connection. In case your Redis instance has password, please set password via `REDIS_PASSWORD` environment variable.
Also, Cube.js requires [Redis](https://redis.io/), in-memory data structure store, to run in production.
It uses Redis for query caching and queue.
Set `REDIS_URL` environment variable to provide Cube.js with Redis connection. In case your Redis instance has password, please set password via `REDIS_PASSWORD` environment variable.
Make sure, your Redis allows at least 15 concurrent connections.
Set `REDIS_TLS` env variable to `true` if you want to enable secure connection.

Expand Down Expand Up @@ -65,7 +65,7 @@ app.listen(port, (err) => {
console.error('Fatal error during server start: ');
console.error(e.stack || e);
}
console.log(`πŸš€ Cube.js server is listening on ${port}`);
console.log(`πŸš€ Cube.js server (${CubejsServerCore.version()}) is listening on ${port}`);
});
```

Expand Down Expand Up @@ -143,7 +143,7 @@ server.listen(port, (err) => {
console.error('Fatal error during server start: ');
console.error(e.stack || e);
}
console.log(`πŸš€ Cube.js server is listening on ${port}`);
console.log(`πŸš€ Cube.js server (${CubejsServerCore.version()}) is listening on ${port}`);
});
```

Expand Down Expand Up @@ -370,7 +370,7 @@ $ docker stop cubejs-docker-demo

## Docker Compose

To run the server in docker-compose we need to add a redis server and a .env file to include the environment variables needed to connect to the database, the secret api secret and redis hostname.
To run the server in docker-compose we need to add a redis server and a .env file to include the environment variables needed to connect to the database, the secret api secret and redis hostname.

Example .env file

Expand Down Expand Up @@ -411,7 +411,7 @@ Build the containers
$ docker-compose build
```

### Start/Stop the containers
### Start/Stop the containers

```bash
$ docker-compose up
Expand All @@ -420,5 +420,3 @@ $ docker-compose up
```bash
$ docker-compose stop
```


40 changes: 20 additions & 20 deletions docs/Cube.js-Backend/Multitenancy-Setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Cube.js supports multitenancy out of the box, both on database and data schema l
Multiple drivers are also supported, meaning that you can have one customer’s data in MongoDB and others in Postgres with one Cube.js instance.

There are 7 [configuration options](@cubejs-backend-server-core#options-reference) you can leverage to make your multitenancy setup.
You can use all of them or just a couple, depending on your specific case.
You can use all of them or just a couple, depending on your specific case.
The options are:

- `contextToAppId`
Expand Down Expand Up @@ -62,20 +62,20 @@ const server = new CubejsServer({
} else if (dataSource === 'googleAnalytics') {
return new BigQueryDriver();
} else if (dataSource === 'financials'){
return new PostgresDriver({
database: 'financials',
host: 'financials-db.acme.com',
user: process.env.FINANCIALS_DB_USER,
password: process.env.FINANCIALS_DB_PASS
return new PostgresDriver({
database: 'financials',
host: 'financials-db.acme.com',
user: process.env.FINANCIALS_DB_USER,
password: process.env.FINANCIALS_DB_PASS
});
} else {
return new PostgresDriver();
}
}
});

server.listen().then(({ port }) => {
console.log(`πŸš€ Cube.js server is listening on ${port}`);
server.listen().then(({ version, port }) => {
console.log(`πŸš€ Cube.js server (${version}) is listening on ${port}`);
});
```

Expand Down Expand Up @@ -103,8 +103,8 @@ const server = new CubejsServer({
}
});

server.listen().then(({ port }) => {
console.log(`πŸš€ Cube.js server is listening on ${port}`);
server.listen().then(({ version, port }) => {
console.log(`πŸš€ Cube.js server (${version}) is listening on ${port}`);
});
```

Expand Down Expand Up @@ -142,8 +142,8 @@ const server = new CubejsServer({
contextToAppId: ({ authInfo }) => `CUBEJS_APP_${authInfo.appId}_${authInfo.userId}`
});

server.listen().then(({ port }) => {
console.log(`πŸš€ Cube.js server is listening on ${port}`);
server.listen().then(({ version, port }) => {
console.log(`πŸš€ Cube.js server (${version}) is listening on ${port}`);
});
```

Expand All @@ -163,8 +163,8 @@ const server = new CubejsServer({
})
});

server.listen().then(({ port }) => {
console.log(`πŸš€ Cube.js server is listening on ${port}`);
server.listen().then(({ version, port }) => {
console.log(`πŸš€ Cube.js server (${version}) is listening on ${port}`);
});
```

Expand All @@ -182,8 +182,8 @@ const server = new CubejsServer({
preAggregationsSchema: ({ authInfo }) => `pre_aggregations_${authInfo.userId}`
});

server.listen().then(({ port }) => {
console.log(`πŸš€ Cube.js server is listening on ${port}`);
server.listen().then(({ version, port }) => {
console.log(`πŸš€ Cube.js server (${version}) is listening on ${port}`);
});
```

Expand Down Expand Up @@ -224,8 +224,8 @@ const server = new CubejsServer({
}
});

server.listen().then(({ port }) => {
console.log(`πŸš€ Cube.js server is listening on ${port}`);
server.listen().then(({ version, port }) => {
console.log(`πŸš€ Cube.js server (${version}) is listening on ${port}`);
});
```

Expand Down Expand Up @@ -265,8 +265,8 @@ const server = new CubejsServer({
repositoryFactory: ({ authInfo }) => new FileRepository(`schema/${authInfo.appId}`)
});

server.listen().then(({ port }) => {
console.log(`πŸš€ Cube.js server is listening on ${port}`);
server.listen().then(({ version, port }) => {
console.log(`πŸš€ Cube.js server (${version}) is listening on ${port}`);
});
```

Expand Down
12 changes: 6 additions & 6 deletions docs/Cube.js-Backend/Security.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,8 @@ var tlsOptions = {
const cubejsServer = new CubejsServer();
cubejsServer.listen(tlsOptions).then(({ tlsPort }) => {
console.log(`πŸš€ Cube.js server is listening securely on ${tlsPort}`);
cubejsServer.listen(tlsOptions).then(({ version, tlsPort }) => {
console.log(`πŸš€ Cube.js server (${version}) is listening securely on ${tlsPort}`);
});
```
Expand Down Expand Up @@ -209,10 +209,10 @@ async function main() {
const certOptions = { days: 2, selfSigned: true };
const tlsOptions = await createCertificate(certOptions);
const ({ tlsPort, server }) = await cubejsServer.listen(tlsOptions);
console.log(`πŸš€ Cube.js server is listening securely on ${tlsPort}`);
const ({ version, tlsPort, server }) = await cubejsServer.listen(tlsOptions);
console.log(`πŸš€ Cube.js server (${version}) is listening securely on ${tlsPort}`);
scheduleCertificateRenewal(server, certOptions, (err, result) => {
if (err !== null) {
console.error(
Expand Down
4 changes: 2 additions & 2 deletions examples/d3-dashboard/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const http = require("http");
const serveStatic = require('serve-static');
require('dotenv').config();

var app = express();
const app = express();
app.use(bodyParser.json({ limit: "50mb" }));
app.use(require('cors')());

Expand All @@ -26,5 +26,5 @@ const port = process.env.PORT || 4000;
const server = http.createServer({}, app);

server.listen(port, () => {
console.log(`πŸš€ Cube.js server is listening on ${port}`);
console.log(`πŸš€ Cube.js server (${CubejsServerCore.version()}) is listening on ${port}`);
});
Loading

0 comments on commit d2f1732

Please sign in to comment.