mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of github.com:arangodb/arangodb into devel
This commit is contained in:
commit
d957549f35
|
@ -2,11 +2,11 @@
|
|||
|
||||
Instead of (or in addition to) defining controllers, Foxx apps can also define exports.
|
||||
|
||||
Foxx exports are not intended to replace regular npm modules. They simply allow you to make your app's collections and *applicationContext* available in other Foxx apps or bundling ArangoDB-specific modules in re-usable Foxx apps.
|
||||
Foxx exports are not intended to replace regular NPM modules. They simply allow you to make your app's collections and **applicationContext** available in other Foxx apps or bundling ArangoDB-specific modules in re-usable Foxx apps.
|
||||
|
||||
!SECTION Define an export module
|
||||
|
||||
In order to export modules in a Foxx app, you need to list the files in your manifest:
|
||||
In order to export modules in a Foxx app you need to list the files in your manifest:
|
||||
|
||||
```json
|
||||
{
|
||||
|
@ -23,7 +23,7 @@ In order to export modules in a Foxx app, you need to list the files in your man
|
|||
}
|
||||
```
|
||||
|
||||
The file *doodads.js* in the app's base path could look like this:
|
||||
The file **doodads.js** in the app's base path could look like this:
|
||||
|
||||
```js
|
||||
var Foxx = require('org/arangodb/foxx');
|
||||
|
@ -36,19 +36,19 @@ exports.repo = doodadRepo;
|
|||
exports.model = Doodad;
|
||||
```
|
||||
|
||||
This module would then export the name "repo" bound to the variable *doodads* as well as the name "model" bound to the *Doodad* model.
|
||||
This module would then export the name "repo" bound to the variable **doodads** as well as the name "model" bound to the **Doodad** model.
|
||||
|
||||
**Note**: that the *applicationContext* is available to your Foxx exports just like in your Foxx controllers.
|
||||
**Note**: The **applicationContext** is available to your Foxx exports just like in your Foxx controllers.
|
||||
|
||||
**Warning**
|
||||
|
||||
Foxx exports only support CommonJS exports using the special *exports* variable. Node-style exports via *module.exports* are not supported.
|
||||
Foxx exports only support CommonJS exports using the special **exports** variable. Node-style exports via **module.exports** are not supported.
|
||||
|
||||
!SECTION Import from another app
|
||||
|
||||
In order to import from another app, you need to know where the app is mounted.
|
||||
|
||||
Let's say we have mounted the example app above at */my-doodads*. We could now access the app's exports in another app like so:
|
||||
Let's say we have mounted the example app above at **/my-doodads**. We could now access the app's exports in another app like so:
|
||||
|
||||
```js
|
||||
var Foxx = require('org/arangodb/foxx');
|
||||
|
@ -65,7 +65,7 @@ doodadRepo.save(myDoodad);
|
|||
|
||||
When using Foxx exports in other apps, the load order of apps determines when which app's exports will become available.
|
||||
|
||||
In order to use Foxx exports in another app's controllers it is recommended you use *controller.addInjector* to delay the import until all mounted apps have been loaded:
|
||||
In order to use Foxx exports in another app's controllers it is recommended you use **controller.addInjector** to delay the import until all mounted apps have been loaded:
|
||||
|
||||
```js
|
||||
var Foxx = require('org/arangodb/foxx');
|
||||
|
@ -86,11 +86,11 @@ controller.post('/doodads', function(request, response, injected) {
|
|||
|
||||
There is currently no workaround to allow using one app's Foxx exports in another app's Foxx exports.
|
||||
|
||||
If you want to import Foxx exports of an app in controllers of the same app, you can do so without knowing the mount path in advance by using *applicationContext.mount*:
|
||||
If you want to import Foxx exports of an app in controllers of the same app, you can do so without knowing the mount path in advance by using **applicationContext.mount**:
|
||||
|
||||
```js
|
||||
var Foxx = require('org/arangodb/foxx');
|
||||
var doodads = Foxx.requireApp(applicationContext.mount).doodads;
|
||||
```
|
||||
|
||||
If you don't need direct access to ArangoDB's functionality or the *applicationContext*, it is a better idea to use a regular npm module instead.
|
||||
If you don't need direct access to ArangoDB's functionality or the **applicationContext**, it is a better idea to use a regular NPM module instead.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
!CHAPTER Foxx Dependency Injection
|
||||
|
||||
If you have runtime dependencies you want to access in your route handlers but don't want to define at load time (e.g. dependencies between multiple Foxx apps), *FoxxController* allows you to inject these dependencies into your route handlers by adding injectors to it.
|
||||
If you have runtime dependencies you want to access in your route handlers but don't want to define at load time (e.g. dependencies between multiple Foxx apps), **FoxxController** allows you to inject these dependencies into your route handlers by adding injectors to it.
|
||||
|
||||
!SECTION Add an injector
|
||||
|
||||
|
@ -8,18 +8,18 @@ Registers a dependency factory with the controller.
|
|||
|
||||
`controller.addInjector(name, factory)`
|
||||
|
||||
The injected dependency will be available as a property with the chosen *name* on the third argument passed to each route handler.
|
||||
The injected dependency will be available as a property with the chosen **name** on the third argument passed to each route handler.
|
||||
|
||||
If *factory* is a function, it will be called the first time a route of that controller is handled and its result will be injected into each route handler. Otherwise the value will be injected as it is.
|
||||
If **factory** is a function, it will be called the first time a route of that controller is handled and its result will be injected into each route handler. Otherwise the value will be injected as it is.
|
||||
|
||||
If you want to inject a function as a dependency, you need to wrap it in a function.
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *name*: the name under which the dependency will be available in the route handler.
|
||||
* *factory*: a function returning the dependency or an arbitrary value that will be passed as-is.
|
||||
* **name**: the name under which the dependency will be available in the route handler
|
||||
* **factory**: a function returning the dependency or an arbitrary value that will be passed as-is
|
||||
|
||||
*Examples*
|
||||
**Examples**
|
||||
|
||||
```js
|
||||
function myFunc() {
|
||||
|
@ -44,13 +44,13 @@ Registers multiple dependency factories with the controller.
|
|||
|
||||
`controller.addInjector(object)`
|
||||
|
||||
Equivalent to calling *addInjector(name, value)* for each property of the object.
|
||||
Equivalent to calling **addInjector(name, value)** for each property of the object.
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *object*: an object mapping dependency names to dependency factories.
|
||||
* **object**: an object mapping dependency names to dependency factories
|
||||
|
||||
*Examples*
|
||||
**Examples**
|
||||
|
||||
```js
|
||||
function myFunc() {
|
||||
|
@ -69,4 +69,4 @@ controller.get('/some/route', function(request, response, injected) {
|
|||
fn: injected.fn.name // 'myFunc'
|
||||
});
|
||||
});
|
||||
```
|
||||
```
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
!CHAPTER Advanced functions
|
||||
|
||||
This chapter is about the more advanced features of foxx.
|
||||
It requires that you have understood all chapters before as these are getting rather close to the core of foxx.
|
||||
This chapter is about the more advanced features of Foxx.
|
||||
It requires that you have understood all chapters before as these are getting rather close to the core of Foxx.
|
||||
|
||||
The first advanced feature of foxx is to write foxx exports.
|
||||
They are used to define an internal api that can be used by other foxxes but is not exposed publicly.
|
||||
One use case for foxx exports is a user management:
|
||||
You want to have it centralized and accessible by other foxxes as a shared user-base.
|
||||
Though each foxx should offer it's own customized login and register functionality on top of that and you only want this one exposed.
|
||||
The first advanced feature of Foxx is to write Foxx exports.
|
||||
They are used to define an internal API that can be used by other Foxxes but is not exposed publicly.
|
||||
One use case for Foxx exports is a user management:
|
||||
You want to have it centralized and accessible by other Foxxes as a shared user-base.
|
||||
Though each Foxx should offer its own customized login and register functionality on top of that and you only want this one exposed.
|
||||
|
||||
So the user management can be implemented using [Exports](Foxx/Advanced/Exports.md).
|
||||
So the user management can be implemented using [Exports](../Advanced/Exports.md).
|
||||
|
||||
But you would also like to make use of an application with exports in other foxxes.
|
||||
The counterpart of exports is [Dependency Injection](Foxx/Advanced/Injection.md) described thereafter.
|
||||
But you would also like to make use of an application with exports in other Foxxes.
|
||||
The counterpart of exports is [Dependency Injection](../Advanced/Injection.md) described thereafter.
|
||||
|
|
|
@ -6,14 +6,14 @@ The sessions app provides a session storage JavaScript API that can be used in o
|
|||
|
||||
This app has the following configuration options:
|
||||
|
||||
* *timeToLive* (optional): number of milliseconds until the session expires or *0* to disable session expiry. Default: *604800000* (one week).
|
||||
* *ttlType* (optional): attribute against which the *timeToLive* is enforced. Valid options: *lastAccess*, *lastUpdate*, *created*. Default: *"created"*.
|
||||
* *sidTimestamp* (optional): whether to append a timestamp to the random part of generated session IDs. Default: *false*.
|
||||
* *sidLength* (optional): number of random characters to use for new session IDs. Default *20*.
|
||||
* **timeToLive** (optional): number of milliseconds until the session expires or **0** to disable session expiry. Default: **604800000** (one week)
|
||||
* **ttlType** (optional): attribute against which the **timeToLive** is enforced. Valid options: **lastAccess**, **lastUpdate**, **created**. Default: **"created"**
|
||||
* **sidTimestamp** (optional): whether to append a timestamp to the random part of generated session IDs. Default: **false**
|
||||
* **sidLength** (optional): number of random characters to use for new session IDs. Default **20**
|
||||
|
||||
!SECTION JavaScript API: *sessionStorage*
|
||||
!SECTION JavaScript API: **sessionStorage**
|
||||
|
||||
This app exposes a session storage via a JavaScript API named *sessionStorage*.
|
||||
This app exposes a session storage via a JavaScript API named **sessionStorage**.
|
||||
|
||||
@EXAMPLES
|
||||
|
||||
|
@ -29,7 +29,7 @@ Indicates a session could not be found in the database.
|
|||
|
||||
`new sessionStorage.errors.SessionNotFound(sessionId)`
|
||||
|
||||
Thrown by the session storage's *delete* and *get* methods if passed a session ID that does not exist in the database.
|
||||
Thrown by the session storage's **delete** and **get** methods if passed a session ID that does not exist in the database.
|
||||
|
||||
@EXAMPLES
|
||||
|
||||
|
@ -47,7 +47,7 @@ Indicates the session exists in the database but has expired.
|
|||
|
||||
`new sessionStorage.errors.SessionExpired(sessionId)`
|
||||
|
||||
Thrown by the session storage's *get* method if passed a session ID for a session that has expired. See also this app's configuration options.
|
||||
Thrown by the session storage's **get** method if passed a session ID for a session that has expired. See also this app's configuration options.
|
||||
|
||||
@EXAMPLES
|
||||
|
||||
|
@ -64,12 +64,12 @@ try {
|
|||
|
||||
Session objects are instances of a Foxx model with the following attributes:
|
||||
|
||||
* *sessionData*: volatile session data. This can be an arbitrary object that will be stored with the session in the database. If you want to store session-specific (rather than user-specific) data in the database, this is the right place for that.
|
||||
* *uid*: the session's active user's *_key* or *undefined* (no active user).
|
||||
* *userData*: the session's active user's *userData* attribute or an empty object.
|
||||
* *created*: timestamp the session was created at.
|
||||
* *lastAccess*: timestamp of the last time the session was fetched from the database.
|
||||
* *lastUpdate*: timestamp of the last time the session was written to the database.
|
||||
* **sessionData**: volatile session data. This can be an arbitrary object that will be stored with the session in the database. If you want to store session-specific (rather than user-specific) data in the database, this is the right place for that
|
||||
* **uid**: the sessions active users **_key** or **undefined** (no active user)
|
||||
* **userData**: the session's active users **userData** attribute or an empty object
|
||||
* **created**: timestamp the session was created at
|
||||
* **lastAccess**: timestamp of the last time the session was fetched from the database
|
||||
* **lastUpdate**: timestamp of the last time the session was written to the database
|
||||
|
||||
!SUBSECTION Create a session
|
||||
|
||||
|
@ -77,9 +77,9 @@ Creates and saves a new instance of the session model.
|
|||
|
||||
`sessionStorage.create(sessionData)`
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *sessionData* (optional): an arbitrary object that will be stored as the session's *sessionData* attribute when the model is saved to the database.
|
||||
* **sessionData** (optional): an arbitrary object that will be stored as the sessions **sessionData** attribute when the model is saved to the database.
|
||||
|
||||
@EXAMPLES
|
||||
|
||||
|
@ -94,11 +94,11 @@ Fetch a session from the database for a given ID.
|
|||
|
||||
`sessionStorage.get(sessionId)`
|
||||
|
||||
Attempts to load the session with the given session ID from the database. If the session does not exist, a *SessionNotFound* exception will be thrown. If the session does exist, but has already expired, a *SessionExpired* exception will be thrown instead.
|
||||
Attempts to load the session with the given session ID from the database. If the session does not exist, a **SessionNotFound** exception will be thrown. If the session does exist, but has already expired, a **SessionExpired** exception will be thrown instead.
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *sessionId*: a session *_key*.
|
||||
* **sessionId**: a session **_key**
|
||||
|
||||
@EXAMPLES
|
||||
|
||||
|
@ -110,7 +110,7 @@ var session = sessionStorage.get(sessionId);
|
|||
|
||||
There are two ways to delete a session from the database:
|
||||
|
||||
* calling the session storage's *delete* method with a session ID directly
|
||||
* calling the session storages **delete** method with a session ID directly
|
||||
* telling a session to delete itself
|
||||
|
||||
!SUBSUBSECTION Delete a session by its ID
|
||||
|
@ -119,11 +119,11 @@ Delete a session with a given ID.
|
|||
|
||||
`sessionStorage.delete(sessionId)`
|
||||
|
||||
Attempts to delete the session with the given session ID from the database. If the session does not exist, a *SessionNotFound* exception will be thrown. The method always returns *null*.
|
||||
Attempts to delete the session with the given session ID from the database. If the session does not exist, a **SessionNotFound** exception will be thrown. The method always returns **null**.
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *sessionId*: a session *_key*.
|
||||
* **sessionId**: a session **_key**.
|
||||
|
||||
@EXAMPLES
|
||||
|
||||
|
@ -139,9 +139,9 @@ Delete a session from the database.
|
|||
|
||||
Attempts to delete the session from the database.
|
||||
|
||||
Returns *true* if the session was deleted successfully.
|
||||
Returns **true** if the session was deleted successfully.
|
||||
|
||||
Returns *false* if the session already didn't exist.
|
||||
Returns **false** if the session already didn't exist.
|
||||
|
||||
@EXAMPLES
|
||||
|
||||
|
@ -170,11 +170,11 @@ Set the active user of a session.
|
|||
|
||||
`session.setUser(user)`
|
||||
|
||||
Expects a Foxx model with a *userData* attribute and sets the session's *uid* attribute to the model's *_key* and the session's *userData* attribute to the model's *userData* attribute.
|
||||
Expects a Foxx model with a **userData** attribute and sets the sessions **uid** attribute to the models **_key** and the sessions **userData** attribute to the models **userData** attribute.
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *user*: instance of a Foxx model with a *`userData* attribute.
|
||||
* **user**: instance of a Foxx model with a **userData** attribute
|
||||
|
||||
@EXAMPLES
|
||||
|
||||
|
@ -190,7 +190,7 @@ Get a session's expiry state.
|
|||
|
||||
`session.hasExpired()`
|
||||
|
||||
Returns *true* if the session's expiry time lies in the past, *false* otherwise.
|
||||
Returns **true** if the sessions expiry time lies in the past, **false** otherwise.
|
||||
|
||||
!SUBSECTION Determine when a session will expire
|
||||
|
||||
|
@ -198,7 +198,7 @@ Get a session's expiry time.
|
|||
|
||||
`session.getExpiry()`
|
||||
|
||||
Returns an integer representing the UTC timestamp in milliseconds at which the session will expire, or *Infinity* (indicating the session will never expire) if session expiry is disabled.
|
||||
Returns an integer representing the UTC timestamp in milliseconds at which the session will expire, or **Infinity** (indicating the session will never expire) if session expiry is disabled.
|
||||
|
||||
!SUBSECTION Determine the TTL of a session
|
||||
|
||||
|
@ -206,4 +206,4 @@ Get a session's time to live.
|
|||
|
||||
`session.getTTL()`
|
||||
|
||||
Returns an integer representing number of milliseconds until the session will expire, or *Infinity* (indicating the session will never expire) if session expiry is disabled.
|
||||
Returns an integer representing number of milliseconds until the session will expire, or **Infinity** (indicating the session will never expire) if session expiry is disabled.
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
!CHAPTER The Simple Authentication App
|
||||
|
||||
The simple auth app provides hashed password-based authentication with automatically generated salts and constant-time password verification.
|
||||
The simple authentication app provides hashed password-based authentication with automatically generated salts and constant-time password verification.
|
||||
|
||||
!SECTION Configuration
|
||||
|
||||
This app has the following configuration options:
|
||||
|
||||
* *saltLength* (optional): length of newly generated salts. Default: *16*.
|
||||
* *hashMethod* (optional): hash algorithm to use. Supported values: *sha1*, *sha224*, *sha256*, *md5*. Default: *"sha256"*.
|
||||
* **saltLength** (optional): length of newly generated salts. Default: **16**
|
||||
* **hashMethod** (optional): hash algorithm to use. Supported values: **sha1**, **sha224**, **sha256**, **md5**. Default: **"sha256"**
|
||||
|
||||
!SECTION JavaScript API: *auth*
|
||||
!SECTION JavaScript API: **auth**
|
||||
|
||||
This app exposes its functionality via a JavaScript API named *auth*.
|
||||
This app exposes its functionality via a JavaScript API named **auth**.
|
||||
|
||||
@EXAMPLES
|
||||
|
||||
|
@ -27,13 +27,13 @@ Generates an authentication object for a given password.
|
|||
|
||||
Returns an authentication object with the following properties:
|
||||
|
||||
* *hash*: the generated hex-encoded hash.
|
||||
* *salt*: the salt used to generate the hash.
|
||||
* *method*: the algorithm used to generate the hash.
|
||||
* **hash**: the generated hex-encoded hash
|
||||
* **salt**: the salt used to generate the hash
|
||||
* **method**: the algorithm used to generate the hash
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *password*: the password to hash.
|
||||
* *password*: the password to hash
|
||||
|
||||
!SUBSECTION Verify a password
|
||||
|
||||
|
@ -41,9 +41,9 @@ Verifies a password against a given authentication object.
|
|||
|
||||
`auth.verifyPassword(authData, password)`
|
||||
|
||||
Generates a hash for the given password using the *salt* and *method* stored in the authentication object and performs a constant time string comparison on them. Returns *true* if the password is valid or *false* otherwise.
|
||||
Generates a hash for the given password using the **salt** and **method** stored in the authentication object and performs a constant time string comparison on them. Returns **true** if the password is valid or **false** otherwise.
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *authData*: an authentication object.
|
||||
* *password*: a password to verify.
|
||||
* **authData**: an authentication object
|
||||
* **password**: a password to verify
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
!CHAPTER The Users App
|
||||
|
||||
The users app provides a username-based user storage JavaScript API that can be used in other Foxx apps.
|
||||
The users app provides an username-based user storage JavaScript API that can be used in other Foxx apps.
|
||||
|
||||
!SECTION JavaScript API: *userStorage*
|
||||
!SECTION JavaScript API: **userStorage**
|
||||
|
||||
This app exposes a user storage via a JavaScript API named *userStorage*.
|
||||
This app exposes an user storage via a JavaScript API named **userStorage**.
|
||||
|
||||
@EXAMPLES
|
||||
|
||||
|
@ -16,11 +16,11 @@ var userStorage = Foxx.requireApp('/_system/users').userStorage;
|
|||
|
||||
!SUBSUBSECTION User Not Found
|
||||
|
||||
Indicates a user could not be found in the database.
|
||||
Indicates an user could not be found in the database.
|
||||
|
||||
`new userStorage.errors.UserNotFound(userId)`
|
||||
|
||||
Thrown by the user storage's *delete* and *get* methods if passed a user ID that does not exist in the database.
|
||||
Thrown by the user storages **delete** and **get** methods if passed an user ID that does not exist in the database.
|
||||
|
||||
@EXAMPLES
|
||||
|
||||
|
@ -34,11 +34,11 @@ try {
|
|||
|
||||
!SUBSUBSECTION Username Not Available
|
||||
|
||||
Indicates a username is already in use.
|
||||
Indicates an username is already in use.
|
||||
|
||||
`new userStorage.errors.UsernameNotAvailable(username)`
|
||||
|
||||
Thrown by the user storage's *create* method if passed a *userData* object with a *username* that is already in use.
|
||||
Thrown by the user storages **create** method if passed a **userData** object with a **username** that is already in use.
|
||||
|
||||
@EXAMPLES
|
||||
|
||||
|
@ -54,25 +54,25 @@ try {
|
|||
|
||||
User objects are instances of a Foxx model with the following attributes:
|
||||
|
||||
* *user*: the user's unique *username*.
|
||||
* *userData*: application-specific user data.
|
||||
* *authData*: an arbitrary object used by authentication apps to store sensitive data. For password authentication this could be a hash, for third-party authentication services this could be information about the user's identity. This attribute should never be exposed to the user directly.
|
||||
* **user**: the user's unique **username**
|
||||
* **userData**: application-specific user data
|
||||
* **authData**: an arbitrary object used by authentication apps to store sensitive data. For password authentication this could be a hash, for third-party authentication services this could be information about the user's identity. This attribute should never be exposed to the user directly
|
||||
|
||||
!SUBSECTION Create a user
|
||||
!SUBSECTION Create an user
|
||||
|
||||
Creates and saves a new instance of the user model.
|
||||
|
||||
`userStorage.create(username, [userData,] [authData])`
|
||||
|
||||
Throws *UsernameNotAvailable* if a user with the given username already exists.
|
||||
Throws **UsernameNotAvailable** if an user with the given username already exists.
|
||||
|
||||
**Note:** When using the system users app (mounted at */\_system/users*), new users will automatically have their *active* flag set to *true* if no value is provided in the *authData* (or if *authData* is omitted entirely).
|
||||
**Note:** When using the system users app (mounted at **/\_system/users**), new users will automatically have their **active** flag set to **true** if no value is provided in the **authData** (or if **authData** is omitted entirely).
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *username*: an arbitrary string that will be used as the user's username
|
||||
* *userData* (optional): an arbitrary object that will be stored as the user's *userData* attribute when the model is saved to the database.
|
||||
* *authData* (optional): an arbitrary object that will be stored as the user's *authData* attribute when the model is saved to the database.
|
||||
* **username**: an arbitrary string that will be used as the user's username
|
||||
* **userData** (optional): an arbitrary object that will be stored as the user's **userData** attribute when the model is saved to the database
|
||||
* **authData** (optional): an arbitrary object that will be stored as the user's **authData** attribute when the model is saved to the database
|
||||
|
||||
@EXAMPLES
|
||||
|
||||
|
@ -83,22 +83,22 @@ assertEqual(user.get('userData').hair, 'fuzzy');
|
|||
|
||||
!SUBSECTION Fetch an existing user
|
||||
|
||||
There are two ways to fetch a user via the user storage API:
|
||||
There are two ways to fetch an user via the user storage API:
|
||||
|
||||
* resolving a *username* with the user storage's *resolve* method
|
||||
* calling the user storage's *get* method with a user ID directly
|
||||
* resolving a **username** with the user storages **resolve** method
|
||||
* calling the user storages **get** method with an user ID directly
|
||||
|
||||
!SUBSUBSECTION Resolve a *username*
|
||||
!SUBSUBSECTION Resolve a **username**
|
||||
|
||||
Fetches a user with a given *username*.
|
||||
Fetches an user with a given **username**.
|
||||
|
||||
`userStorage.resolve(username)`
|
||||
|
||||
If the username can not be resolved, a *UserNotFound* exception will be thrown instead.
|
||||
If the username can not be resolved, a **UserNotFound** exception will be thrown instead.
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *username*: an arbitrary string matching the username of the user you are trying to fetch.
|
||||
* **username**: an arbitrary string matching the username of the user you are trying to fetch.
|
||||
|
||||
@EXAMPLES
|
||||
|
||||
|
@ -107,17 +107,17 @@ var user = userStorage.resolve('malaclypse');
|
|||
assertEqual(user.user, 'malaclypse');
|
||||
```
|
||||
|
||||
!SUBSUBSECTION Resolve a user ID directly
|
||||
!SUBSUBSECTION Resolve an user ID directly
|
||||
|
||||
Fetches a user with a given ID.
|
||||
Fetches an user with a given ID.
|
||||
|
||||
`userStorage.get(userId)`
|
||||
|
||||
Attempts to fetch the user with the given ID from the database. If the user does not exist, a *UserNotFound* exception will be thrown instead.
|
||||
Attempts to fetch the user with the given ID from the database. If the user does not exist, an **UserNotFound** exception will be thrown instead.
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *userId*: a user *_key*.
|
||||
* **userId**: an user **_key**.
|
||||
|
||||
@EXAMPLES
|
||||
|
||||
|
@ -126,24 +126,24 @@ var user = userStorage.get(userId);
|
|||
assertEqual(user.get('_key'), userId);
|
||||
```
|
||||
|
||||
!SUBSECTION Delete a user
|
||||
!SUBSECTION Delete an user
|
||||
|
||||
There are two ways to delete a user from the database:
|
||||
There are two ways to delete an user from the database:
|
||||
|
||||
* calling the user storage's *delete* method with a user ID directly
|
||||
* telling a user to delete itself
|
||||
* calling the user storages **delete** method with an user ID directly
|
||||
* telling an user to delete itself
|
||||
|
||||
!SUBSUBSECTION Delete a user by its ID
|
||||
!SUBSUBSECTION Delete an user by its ID
|
||||
|
||||
Delete a user with a given ID.
|
||||
Delete an user with a given ID.
|
||||
|
||||
`userStorage.delete(userId)`
|
||||
|
||||
Attempts to delete the user with the given user ID from the database. If the user does not exist, a *UserNotFound* exception will be thrown. The method always returns *null*.
|
||||
Attempts to delete the user with the given user ID from the database. If the user does not exist, a **UserNotFound** exception will be thrown. The method always returns **null**.
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *userId*: a user *_key*.
|
||||
* **userId**: an user **_key**.
|
||||
|
||||
@EXAMPLES
|
||||
|
||||
|
@ -151,17 +151,17 @@ Attempts to delete the user with the given user ID from the database. If the use
|
|||
userStorage.delete(userId);
|
||||
```
|
||||
|
||||
!SUBSUBSECTION Tell a user to delete itself
|
||||
!SUBSUBSECTION Tell an user to delete itself
|
||||
|
||||
Delete a user from the database.
|
||||
Delete an user from the database.
|
||||
|
||||
`user.delete()`
|
||||
|
||||
Attempts to delete the user from the database.
|
||||
|
||||
Returns *true* if the user was deleted successfully.
|
||||
Returns **true** if the user was deleted successfully.
|
||||
|
||||
Returns *false* if the user already didn't exist.
|
||||
Returns **false** if the user already didn't exist.
|
||||
|
||||
@EXAMPLES
|
||||
|
||||
|
@ -170,13 +170,13 @@ var user = userStorage.get(userId);
|
|||
user.delete();
|
||||
```
|
||||
|
||||
!SUBSECTION Save a user
|
||||
!SUBSECTION Save an user
|
||||
|
||||
Save a user to the database.
|
||||
Save an user to the database.
|
||||
|
||||
`user.save()`
|
||||
|
||||
In order to commit changes made to the user in your code, you need to call this method.
|
||||
In order to commit changes made to the user in your code you need to call this method.
|
||||
|
||||
@EXAMPLES
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
!CHAPTER Administrative Scripts in Cluster
|
||||
|
||||
If you want to scale the dataset you access via foxx you have to take sharding into account.
|
||||
If you want to scale the dataset you access via Foxx you have to take sharding into account.
|
||||
This results in minor changes to your setup and teardown scripts.
|
||||
These will be executed on all servers you deploy your foxx to, hence you have to consider that they will be executed multiple times.
|
||||
These will be executed on all servers you deploy your Foxx to, hence you have to consider that they will be executed multiple times.
|
||||
Also the setup for collections now requires you to give the amount of shards for the collection (recommended is the amount of servers squared).
|
||||
|
||||
!SECTION Setup script
|
||||
|
@ -10,42 +10,47 @@ Also the setup for collections now requires you to give the amount of shards for
|
|||
This script has to take into consideration that collections might have been installed by other servers already.
|
||||
Also you have to give the amount of shards (9 in this example):
|
||||
|
||||
var console = require("console");
|
||||
var arangodb = require("org/arangodb");
|
||||
var db = arangodb.db;
|
||||
```
|
||||
var console = require("console");
|
||||
var arangodb = require("org/arangodb");
|
||||
var db = arangodb.db;
|
||||
|
||||
var texts = applicationContext.collectionName("texts");
|
||||
|
||||
if (db._collection(texts) === null) {
|
||||
// This is the first one running the script
|
||||
var collection = db._create(texts, {
|
||||
numberOfShards: 9
|
||||
});
|
||||
collection.save({ text: "entry 1 from collection texts" });
|
||||
collection.save({ text: "entry 2 from collection texts" });
|
||||
collection.save({ text: "entry 3 from collection texts" });
|
||||
}
|
||||
else {
|
||||
console.log("collection '%s' already exists. Leaving it untouched.", texts);
|
||||
}
|
||||
var texts = applicationContext.collectionName("texts");
|
||||
|
||||
if (db._collection(texts) === null) {
|
||||
// This is the first one running the script
|
||||
var collection = db._create(texts, {
|
||||
numberOfShards: 9
|
||||
});
|
||||
collection.save({ text: "entry 1 from collection texts" });
|
||||
collection.save({ text: "entry 2 from collection texts" });
|
||||
collection.save({ text: "entry 3 from collection texts" });
|
||||
}
|
||||
else {
|
||||
console.log("collection '%s' already exists. Leaving it untouched.", texts);
|
||||
}
|
||||
```
|
||||
|
||||
!SECTION Teardown script
|
||||
|
||||
Also this script has to take into account that it might be run several times.
|
||||
You can also omit the teardown execution with passing `teardown:false` options to the uninstall process.
|
||||
|
||||
unix>foxx-manager uninstall /example teardown=false
|
||||
```
|
||||
unix>foxx-manager uninstall /example teardown=false
|
||||
```
|
||||
|
||||
The teardown script just has to check if the collection is not yet dropped:
|
||||
|
||||
var arangodb = require("org/arangodb");
|
||||
var db = arangodb.db;
|
||||
```
|
||||
var arangodb = require("org/arangodb");
|
||||
var db = arangodb.db;
|
||||
|
||||
var texts = applicationContext.collectionName("texts");
|
||||
var collection = db._collection(texts);
|
||||
var texts = applicationContext.collectionName("texts");
|
||||
var collection = db._collection(texts);
|
||||
|
||||
if (collection !== null) {
|
||||
// Not yet dropped. Drop it now
|
||||
collection.drop();
|
||||
}
|
||||
if (collection !== null) {
|
||||
// Not yet dropped. Drop it now
|
||||
collection.drop();
|
||||
}
|
||||
```
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
!CHAPTER Foxx console
|
||||
|
||||
Foxx injects a *console* object into each Foxx app that allows writing log entries to the database and querying them from within the app itself.
|
||||
Foxx injects a **console** object into each Foxx app that allows writing log entries to the database and querying them from within the app itself.
|
||||
|
||||
The *console* object supports the CommonJS Console API found in Node.js and modern browsers, while also providing some ArangoDB-specific additions.
|
||||
The **console** object supports the CommonJS Console API found in Node.js and modern browsers, while also providing some ArangoDB-specific additions.
|
||||
|
||||
!SECTION Logging
|
||||
|
||||
|
@ -16,7 +16,7 @@ Applies `util.format` to the arguments and writes the resulting string to the ap
|
|||
|
||||
If the first argument is not a formatting string or any of the additional arguments are not used by the formatting string, they will be concatenated to the result string.
|
||||
|
||||
*Examples*
|
||||
**Examples**
|
||||
|
||||
```js
|
||||
console.log("%s, %s!", "Hello", "World"); // => "Hello, World!"
|
||||
|
@ -27,22 +27,22 @@ console.log(1, 2, 3); // => "1 2 3"
|
|||
|
||||
!SUBSECTION Logging with different log levels
|
||||
|
||||
The *console* object provides additional methods to log messages with different log levels:
|
||||
The **console** object provides additional methods to log messages with different log levels:
|
||||
|
||||
* `console.debug` for log level *DEBUG*
|
||||
* `console.info` for log level *INFO*
|
||||
* `console.warn` for log level *WARN*
|
||||
* `console.error` for log level *ERROR*
|
||||
* `console.debug` for log level **DEBUG**
|
||||
* `console.info` for log level **INFO**
|
||||
* `console.warn` for log level **WARN**
|
||||
* `console.error` for log level **ERROR**
|
||||
|
||||
By default, `console.log` uses log level *INFO*, making it functionally equivalent to `console.info`. Other than the log level, all of these methods behave identically to `console.log`.
|
||||
By default, `console.log` uses log level **INFO**, making it functionally equivalent to `console.info`. Other than the log level, all of these methods behave identically to `console.log`.
|
||||
|
||||
The built-in log levels are:
|
||||
|
||||
* -2: *TRACE*
|
||||
* -1: *DEBUG*
|
||||
* 0: *INFO*
|
||||
* 1: *WARN*
|
||||
* 2: *ERROR*
|
||||
* -2: **TRACE**
|
||||
* -1: **DEBUG**
|
||||
* 0: **INFO**
|
||||
* 1: **WARN**
|
||||
* 2: **ERROR**
|
||||
|
||||
!SUBSECTION Logging with timers
|
||||
|
||||
|
@ -54,9 +54,9 @@ Passing a label to `console.time` starts the timer. Passing the same label to `c
|
|||
|
||||
Calling `console.timeEnd` with an invalid label or calling it with the same label twice (without first starting a new timer with the same label) results in an error.
|
||||
|
||||
By default, the timing messages will be logged with log level *INFO*.
|
||||
By default, the timing messages will be logged with log level **INFO**.
|
||||
|
||||
*Examples*
|
||||
**Examples**
|
||||
|
||||
```js
|
||||
console.time('do something');
|
||||
|
@ -85,9 +85,9 @@ You can explicitly log a message with a stack trace.
|
|||
|
||||
This creates a stack trace with the given message.
|
||||
|
||||
By default the stack traces will be logged with a log level of *TRACE*.
|
||||
By default the stack traces will be logged with a log level of **TRACE**.
|
||||
|
||||
*Examples*
|
||||
**Examples**
|
||||
|
||||
```js
|
||||
console.trace('Hello');
|
||||
|
@ -104,11 +104,11 @@ This creates an assertion that will log an error if it fails.
|
|||
|
||||
`console.assert(statement, message)`
|
||||
|
||||
If the given *statement* is not truthy (i.e. evaluates to `false` if treated as a boolean), an `AssertionError` with the given message will be created and its stack trace will be logged.
|
||||
If the given **statement** is not true (e.g. evaluates to `false` if treated as a boolean), an `AssertionError` with the given message will be created and its stack trace will be logged.
|
||||
|
||||
By default, the stack trace will be logged with a log level of *ERROR* and the error will be discarded after logging it (instead of being thrown).
|
||||
By default, the stack trace will be logged with a log level of **ERROR** and the error will be discarded after logging it (instead of being thrown).
|
||||
|
||||
*Examples*
|
||||
**Examples**
|
||||
|
||||
```js
|
||||
console.assert(2 + 2 === 5, "I'm bad at maths");
|
||||
|
@ -127,11 +127,11 @@ This logs a more detailed string representation of a given object.
|
|||
|
||||
The regular logging functions try to format messages as nicely and readable as possible. Sometimes that may not provide you with all the information you actually want.
|
||||
|
||||
The *dir* method instead logs the result of `util.inspect`.
|
||||
The **dir** method instead logs the result of `util.inspect`.
|
||||
|
||||
By default, the message will be logged with the log level *INFO*.
|
||||
By default the message will be logged with the log level **INFO**.
|
||||
|
||||
*Examples*
|
||||
**Examples**
|
||||
|
||||
```js
|
||||
console.log(require('org/arangodb').db); // => '[ArangoDatabase "_system"]'
|
||||
|
@ -153,14 +153,14 @@ This lets you define your own log levels.
|
|||
|
||||
If you need more than the built-in log levels, you can easily define your own.
|
||||
|
||||
This method returns a function that logs messages with the given log level (i.e. an equivalent to `console.log` that uses your custom log level instead).
|
||||
This method returns a function that logs messages with the given log level (e.g. an equivalent to `console.log` that uses your custom log level instead).
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *name*: name of the log level as it appears in the database, usually all-uppercase.
|
||||
* *value* (optional): value of the log level. Default: `999`
|
||||
* **name**: name of the log level as it appears in the database, usually all-uppercase
|
||||
* **value** (optional): value of the log level. Default: `999`
|
||||
|
||||
The *value* is used when determining whether a log entry meets the minimum log level that can be defined in various places. For a list of the built-in log levels and their values see the section on logging with different log levels above.
|
||||
The **value** is used when determining whether a log entry meets the minimum log level that can be defined in various places. For a list of the built-in log levels and their values see the section on logging with different log levels above.
|
||||
|
||||
!SUBSECTION Preventing entries from being logged
|
||||
|
||||
|
@ -168,7 +168,7 @@ You can define a minimum log level entries must match in order to be logged.
|
|||
|
||||
`console.setLogLevel(level)`
|
||||
|
||||
The *level* can be a numeric value or the case-sensitive name of an existing log level.
|
||||
The **level** can be a numeric value or the case-sensitive name of an existing log level.
|
||||
|
||||
Any entries with a log level lower than the given value will be discarded silently.
|
||||
|
||||
|
@ -182,7 +182,7 @@ You can toggle the logging of stack trace objects for every log entry.
|
|||
|
||||
`console.setTracing(trace)`
|
||||
|
||||
If *trace* is set to `true`, all log entries will be logged with a parsed stack trace as an additional `stack` property that can be useful for identifying where the entry originated and how the code triggering it was called.
|
||||
If **trace** is set to `true`, all log entries will be logged with a parsed stack trace as an additional `stack` property that can be useful for identifying where the entry originated and how the code triggering it was called.
|
||||
|
||||
Because this results in every logging call creating a stack trace (which may have a significant performance impact), this option is disabled by default.
|
||||
|
||||
|
@ -192,7 +192,7 @@ You can toggle whether console assertions should throw if they fail.
|
|||
|
||||
`console.setAssertThrows(assertThrows)`
|
||||
|
||||
If *assertThrows* is set to `true`, any failed assertions in `console.assert` will result in the generated error being thrown instead of being discarded after it is logged.
|
||||
If **assertThrows** is set to `true`, any failed assertions in `console.assert` will result in the generated error being thrown instead of being discarded after it is logged.
|
||||
|
||||
By default, this setting is disabled.
|
||||
|
||||
|
@ -200,15 +200,15 @@ By default, this setting is disabled.
|
|||
|
||||
Most of the logging methods have an implied log level that is set to a reasonable default. If you would like to have them use different log levels, you can easily change them.
|
||||
|
||||
* `console.log.level` defaults to *INFO*
|
||||
* `console.dir.level` defaults to *INFO*
|
||||
* `console.time.level` defaults to *INFO*
|
||||
* `console.trace.level` defaults to *TRACE*
|
||||
* `console.assert.level` defaults to *ERROR*
|
||||
* `console.log.level` defaults to **INFO**
|
||||
* `console.dir.level` defaults to **INFO**
|
||||
* `console.time.level` defaults to **INFO**
|
||||
* `console.trace.level` defaults to **TRACE**
|
||||
* `console.assert.level` defaults to **ERROR**
|
||||
|
||||
To use different log levels, just set these properties to the case-sensitive name of the desired log level.
|
||||
|
||||
*Examples*
|
||||
**Examples**
|
||||
|
||||
```js
|
||||
console.log('this uses "INFO"');
|
||||
|
@ -249,15 +249,15 @@ It provides three easy methods for querying the log entries:
|
|||
|
||||
Each method takes an optional `opts` argument, which can be an object with any of the following properties:
|
||||
|
||||
* *startTime*: the oldest time to include (in milliseconds). Default: 2 hours ago.
|
||||
* *endTime*: the most recent time to include (in milliseconds).
|
||||
* *level*: only return entries with this log level (name or value).
|
||||
* *minLevel*: only return entries with this log level or above (name or value).
|
||||
* *sort*: sorting direction of the result (*ASC* or *DESC* by time). Default: *ASC*.
|
||||
* *limit*: maximum number of entries to return.
|
||||
* *offset*: if *limit* is set, skip this many entries.
|
||||
* **startTime**: the oldest time to include (in milliseconds). Default: 2 hours ago.
|
||||
* **endTime**: the most recent time to include (in milliseconds).
|
||||
* **level**: only return entries with this log level (name or value).
|
||||
* **minLevel**: only return entries with this log level or above (name or value).
|
||||
* **sort**: sorting direction of the result (**ASC** or **DESC** by time). Default: **ASC**.
|
||||
* **limit**: maximum number of entries to return.
|
||||
* **offset**: if **limit** is set, skip this many entries.
|
||||
|
||||
The default value for *startTime* can be changed by overriding `logs.defaultMaxAge` with a different time offset in milliseconds.
|
||||
The default value for **startTime** can be changed by overriding `logs.defaultMaxAge` with a different time offset in milliseconds.
|
||||
|
||||
!SUBSUBSECTION Search by message
|
||||
|
||||
|
@ -265,7 +265,7 @@ This lists all log entries with messages that contain the given token.
|
|||
|
||||
`logs.searchByMessage(message, [opts])`
|
||||
|
||||
This works like `logs.list` except it only returns log entries containing the given *message* part in their message.
|
||||
This works like `logs.list` except it only returns log entries containing the given **message** part in their message.
|
||||
|
||||
!SUBSUBSECTION Search by file name
|
||||
|
||||
|
@ -273,8 +273,8 @@ This lists all log entries with stack traces that contain the given token.
|
|||
|
||||
`logs.searchByFileName(fileName, [opts])`
|
||||
|
||||
This works like `logs.list` except it only returns log entries containing the given *fileName* part in one of the file names of their stack trace.
|
||||
This works like `logs.list` except it only returns log entries containing the given **fileName** part in one of the file names of their stack trace.
|
||||
|
||||
This method can only be used if the console has *tracing* enabled. See the section on enabling extra stack traces.
|
||||
This method can only be used if the console has **tracing** enabled. See the section on enabling extra stack traces.
|
||||
|
||||
Note that entries that were logged while tracing was not enabled can not be found with this method because they don't have any parsed stack traces associated with them. This method does not search the log entries messages for the file name, so entries generated by `console.assert` or `console.trace` are not treated differently.
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
!SECTION Documenting and constraining a specific route
|
||||
|
||||
If you now want to document your route, you can use JSDoc style comments (a
|
||||
multiline comment block with the first line starting with */*** instead
|
||||
multi-line comment block where the first line starts with */*** instead
|
||||
of */**) above your routes to do that:
|
||||
|
||||
```js
|
||||
|
@ -82,10 +82,10 @@ API by chaining the following methods onto your path definition:
|
|||
|
||||
In addition to documenting a specific route, you can also
|
||||
do the same for all routes of a controller. For this purpose
|
||||
use the *allRoutes* object of the according controller.
|
||||
use the **allRoutes** object of the according controller.
|
||||
The following methods are available.
|
||||
|
||||
*Examples*
|
||||
**Examples**
|
||||
|
||||
Provide an error response for all routes handled by this controller:
|
||||
|
||||
|
@ -147,18 +147,18 @@ When you have created your FoxxController you can now define routes on it.
|
|||
You provide each with a function that will handle the request. It gets two
|
||||
arguments (four, to be honest. But the other two are not relevant for now):
|
||||
|
||||
* The *request* object
|
||||
* The *response* object
|
||||
* The **request** object
|
||||
* The **response** object
|
||||
|
||||
These objects are provided by the underlying ArangoDB actions and enhanced
|
||||
by the *BaseMiddleware* provided by Foxx.
|
||||
by the **BaseMiddleware** provided by Foxx.
|
||||
|
||||
!SUBSECTION The Request Object
|
||||
|
||||
The *request* object inherits several attributes from the underlying Actions:
|
||||
The **request** object inherits several attributes from the underlying Actions:
|
||||
|
||||
* *compatibility*: an integer specifying the compatibility version sent by the
|
||||
client (in request header *x-arango-version*). If the client does not send this
|
||||
* **compatibility**: an integer specifying the compatibility version sent by the
|
||||
client (in request header **x-arango-version**). If the client does not send this
|
||||
header, ArangoDB will set this to the minimum compatible version number. The
|
||||
value is 10000 * major + 100 * minor (e.g. *10400* for ArangoDB version 1.4).
|
||||
|
||||
|
|
|
@ -1,63 +1,71 @@
|
|||
!CHAPTER Available Debugging mechanisms
|
||||
|
||||
We are talking about the development mode for foxx.
|
||||
Hence one of the most important parts will be debugging of your foxx.
|
||||
We are talking about the development mode for Foxx.
|
||||
Hence one of the most important parts will be debugging of your Foxx.
|
||||
We have several mechanisms available to simplify this task.
|
||||
During foxx development we assume the following situation:
|
||||
You have installed a syntactically valid version of a foxx and want to develop it further.
|
||||
During Foxx development we assume the following situation:
|
||||
You have installed a syntactically valid version of a Foxx and want to develop it further.
|
||||
You have activated the development mode for this route:
|
||||
|
||||
unix>foxx-manager development /example
|
||||
Activated development mode for Application hello-foxx version 1.5.0 on mount point /example
|
||||
```
|
||||
unix>foxx-manager development /example
|
||||
Activated development mode for Application hello-foxx version 1.5.0 on mount point /example
|
||||
```
|
||||
|
||||
!SECTION Errors during install
|
||||
|
||||
Now you apply changes to the source code of foxx.
|
||||
In development mode it is possible that you create a foxx that could not be installed regularly.
|
||||
Now you apply changes to the source code of Foxx.
|
||||
In development mode it is possible that you create a Foxx that could not be installed regularly.
|
||||
If this is the case and you request any route of it you should receive a detailed error information:
|
||||
|
||||
unix>curl -X GET --dump - http://localhost:8529/_db/_system/example/failed
|
||||
HTTP/1.1 500 Internal Error
|
||||
Server: ArangoDB
|
||||
Connection: Keep-Alive
|
||||
Content-Type: application/json; charset=utf-8
|
||||
Content-Length: 554
|
||||
```
|
||||
unix>curl -X GET --dump - http://localhost:8529/_db/_system/example/failed
|
||||
HTTP/1.1 500 Internal Error
|
||||
Server: ArangoDB
|
||||
Connection: Keep-Alive
|
||||
Content-Type: application/json; charset=utf-8
|
||||
Content-Length: 554
|
||||
|
||||
{"exception":"Error: App not found","stacktrace":["Error: App not found"," at Object.lookupApp (./js/server/modules/org/arangodb/foxx/manager.js:99:13)"," at foxxRouting (./js/server/modules/org/arangodb/actions.js:1040:27)"," at execute (./js/server/modules/org/arangodb/actions.js:1291:7)"," at Object.routeRequest (./js/server/modules/org/arangodb/actions.js:1312:3)"," at Function.actions.defineHttp.callback (js/actions/api-system.js:51:15)",""],"error":true,"code":500,"errorNum":500,"errorMessage":"failed to load foxx mounted at '/example'"}
|
||||
{"exception":"Error: App not found","stacktrace":["Error: App not found"," at Object.lookupApp (./js/server/modules/org/arangodb/foxx/manager.js:99:13)"," at foxxRouting (./js/server/modules/org/arangodb/actions.js:1040:27)"," at execute (./js/server/modules/org/arangodb/actions.js:1291:7)"," at Object.routeRequest (./js/server/modules/org/arangodb/actions.js:1312:3)"," at Function.actions.defineHttp.callback (js/actions/api-system.js:51:15)",""],"error":true,"code":500,"errorNum":500,"errorMessage":"failed to load foxx mounted at '/example'"}
|
||||
```
|
||||
|
||||
!SECTION Errors in routes
|
||||
|
||||
If you have created a foxx that can be regularly installed but has an unhandled error inside a route.
|
||||
If you have created a Foxx that can be regularly installed but has an unhandled error inside a route.
|
||||
Triggering this route and entering the error case will return the specific error including a stack trace for you to hunt it down:
|
||||
|
||||
unix>curl -X GET http://localhost:8529/_db/_system/example/failed
|
||||
HTTP/1.1 500 Internal Error
|
||||
Server: ArangoDB
|
||||
Connection: Keep-Alive
|
||||
Content-Type: application/json
|
||||
Content-Length: 917
|
||||
```
|
||||
unix>curl -X GET http://localhost:8529/_db/_system/example/failed
|
||||
HTTP/1.1 500 Internal Error
|
||||
Server: ArangoDB
|
||||
Connection: Keep-Alive
|
||||
Content-Type: application/json
|
||||
Content-Length: 917
|
||||
|
||||
{"error":"Unhandled Error","stack":"Error: Unhandled Error\n at fail (js/apps/_db/_system/example/APP/app.js:279:13)\n at js/apps/_db/_system/example/APP/app.js:284:5\n at Object.res.action.callback (./js/server/modules/org/arangodb/foxx/internals.js:108:5)\n at ./js/server/modules/org/arangodb/foxx/routing.js:346:19\n at execute (./js/server/modules/org/arangodb/actions.js:1291:7)\n at next (./js/server/modules/org/arangodb/actions.js:1308:7)\n at [object Object]:386:5\n at execute (./js/server/modules/org/arangodb/actions.js:1291:7)\n at routeRequest (./js/server/modules/org/arangodb/actions.js:1312:3)\n at foxxRouting (./js/server/modules/org/arangodb/actions.js:1082:7)\n at execute (./js/server/modules/org/arangodb/actions.js:1291:7)\n at Object.routeRequest (./js/server/modules/org/arangodb/actions.js:1312:3)\n at Function.actions.defineHttp.callback (js/actions/api-system.js:51:15)\n"}
|
||||
{"error":"Unhandled Error","stack":"Error: Unhandled Error\n at fail (js/apps/_db/_system/example/APP/app.js:279:13)\n at js/apps/_db/_system/example/APP/app.js:284:5\n at Object.res.action.callback (./js/server/modules/org/arangodb/foxx/internals.js:108:5)\n at ./js/server/modules/org/arangodb/foxx/routing.js:346:19\n at execute (./js/server/modules/org/arangodb/actions.js:1291:7)\n at next (./js/server/modules/org/arangodb/actions.js:1308:7)\n at [object Object]:386:5\n at execute (./js/server/modules/org/arangodb/actions.js:1291:7)\n at routeRequest (./js/server/modules/org/arangodb/actions.js:1312:3)\n at foxxRouting (./js/server/modules/org/arangodb/actions.js:1082:7)\n at execute (./js/server/modules/org/arangodb/actions.js:1291:7)\n at Object.routeRequest (./js/server/modules/org/arangodb/actions.js:1312:3)\n at Function.actions.defineHttp.callback (js/actions/api-system.js:51:15)\n"}
|
||||
```
|
||||
|
||||
!SECTION Errors in logs
|
||||
|
||||
Independent of the errors presented in the routes on requests foxxes will always log errors to the log-file if catched by the default error handlers.
|
||||
Independent of the errors presented in the routes on requests Fox will always log errors to the log-file if caught by the default error handlers.
|
||||
The log entries will always contain stacktraces and error messages:
|
||||
|
||||
INFO /example, incoming request from 127.0.0.1: GET http://0.0.0.0:8529/example/failed
|
||||
ERROR Error in foxx route '{ "match" : "/failed", "methods" : [ "get" ] }': 'Unhandled Error', Stacktrace: Error: Unhandled Error
|
||||
ERROR at fail (js/apps/_db/_system/example/APP/app.js:279:13)
|
||||
ERROR at js/apps/_db/_system/example/APP/app.js:284:5
|
||||
ERROR at Object.res.action.callback (./js/server/modules/org/arangodb/foxx/internals.js:108:5)
|
||||
ERROR at ./js/server/modules/org/arangodb/foxx/routing.js:346:19
|
||||
ERROR at execute (./js/server/modules/org/arangodb/actions.js:1291:7)
|
||||
ERROR at next (./js/server/modules/org/arangodb/actions.js:1308:7)
|
||||
ERROR at [object Object]:386:5
|
||||
ERROR at execute (./js/server/modules/org/arangodb/actions.js:1291:7)
|
||||
ERROR at routeRequest (./js/server/modules/org/arangodb/actions.js:1312:3)
|
||||
ERROR at foxxRouting (./js/server/modules/org/arangodb/actions.js:1082:7)
|
||||
ERROR at execute (./js/server/modules/org/arangodb/actions.js:1291:7)
|
||||
ERROR at Object.routeRequest (./js/server/modules/org/arangodb/actions.js:1312:3)
|
||||
ERROR at Function.actions.defineHttp.callback (js/actions/api-system.js:51:15)
|
||||
ERROR
|
||||
INFO /example, outgoing response with status 500 of type application/json, body length: 917
|
||||
```
|
||||
INFO /example, incoming request from 127.0.0.1: GET http://0.0.0.0:8529/example/failed
|
||||
ERROR Error in foxx route '{ "match" : "/failed", "methods" : [ "get" ] }': 'Unhandled Error', Stacktrace: Error: Unhandled Error
|
||||
ERROR at fail (js/apps/_db/_system/example/APP/app.js:279:13)
|
||||
ERROR at js/apps/_db/_system/example/APP/app.js:284:5
|
||||
ERROR at Object.res.action.callback (./js/server/modules/org/arangodb/foxx/internals.js:108:5)
|
||||
ERROR at ./js/server/modules/org/arangodb/foxx/routing.js:346:19
|
||||
ERROR at execute (./js/server/modules/org/arangodb/actions.js:1291:7)
|
||||
ERROR at next (./js/server/modules/org/arangodb/actions.js:1308:7)
|
||||
ERROR at [object Object]:386:5
|
||||
ERROR at execute (./js/server/modules/org/arangodb/actions.js:1291:7)
|
||||
ERROR at routeRequest (./js/server/modules/org/arangodb/actions.js:1312:3)
|
||||
ERROR at foxxRouting (./js/server/modules/org/arangodb/actions.js:1082:7)
|
||||
ERROR at execute (./js/server/modules/org/arangodb/actions.js:1291:7)
|
||||
ERROR at Object.routeRequest (./js/server/modules/org/arangodb/actions.js:1312:3)
|
||||
ERROR at Function.actions.defineHttp.callback (js/actions/api-system.js:51:15)
|
||||
ERROR
|
||||
INFO /example, outgoing response with status 500 of type application/json, body length: 917
|
||||
```
|
||||
|
|
|
@ -16,31 +16,31 @@ The `--javascript.dev-app-path` parameter is not having any effect any more.
|
|||
|
||||
Activating the development mode is done with a single command:
|
||||
|
||||
unix> foxx-manager development /example
|
||||
Activated development mode for Application hello-foxx version 1.5.0 on mount point /example
|
||||
```
|
||||
unix> foxx-manager development /example
|
||||
Activated development mode for Application hello-foxx version 1.5.0 on mount point /example
|
||||
```
|
||||
|
||||
Now the app will now be listed in *listDevelopment*:
|
||||
Now the app will now be listed in **listDevelopment**:
|
||||
|
||||
unix> foxx-manager listDevelopment
|
||||
Mount Name Author Description Version Development
|
||||
--------- ----------- ------------- ----------------------------------------- -------- ------------
|
||||
/example hello-foxx Frank Celler This is 'Hello World' for ArangoDB Foxx. 1.5.0 true
|
||||
--------- ----------- ------------- ----------------------------------------- -------- ------------
|
||||
1 application(s) found
|
||||
```
|
||||
unix> foxx-manager listDevelopment
|
||||
Mount Name Author Description Version Development
|
||||
--------- ----------- ------------- ----------------------------------------- -------- ------------
|
||||
/example hello-foxx Frank Celler This is 'Hello World' for ArangoDB Foxx. 1.5.0 true
|
||||
--------- ----------- ------------- ----------------------------------------- -------- ------------
|
||||
1 application(s) found
|
||||
```
|
||||
|
||||
!SECTION Effects
|
||||
|
||||
For a Foxx application in development mode the following effects apply:
|
||||
<dl>
|
||||
<dt>Reload on request</dt>
|
||||
<dl>
|
||||
Whenever a request is routed to this application it's source is reloaded.
|
||||
This means all requests are slightly slower than in production mode.
|
||||
But you will get immediate live updates on your code changes.
|
||||
</dl>
|
||||
<dt>Exposed Debugging information</dt>
|
||||
<dl>
|
||||
This application will deliver error messages and stack traces to requesting client.
|
||||
For more information see the [Debugging](Debugging.md) section.
|
||||
</dl>
|
||||
</dl>
|
||||
|
||||
**Reload on request**
|
||||
Whenever a request is routed to this application its source is reloaded.
|
||||
This means all requests are slightly slower than in production mode.
|
||||
But you will get immediate live updates on your code changes.
|
||||
|
||||
**Exposed Debugging information**
|
||||
This application will deliver error messages and stack traces to requesting client.
|
||||
For more information see the [Debugging](Debugging.md) section.
|
||||
|
|
|
@ -11,36 +11,42 @@ The route to reach this application via http(s) is constructed with the followin
|
|||
|
||||
Now the route is constructed as follows:
|
||||
|
||||
<arangodb>/_db/<db>/<mount>
|
||||
http://localhost:8529/_db/_system/example
|
||||
```
|
||||
<arangodb>/_db/<db>/<mount>
|
||||
http://localhost:8529/_db/_system/example
|
||||
```
|
||||
|
||||
For the sources of the application the path on your file system the path is constructed almost the same way.
|
||||
But here we need one additional information:
|
||||
But here we need some additional information:
|
||||
|
||||
* The app-path `<app-path>`: (e.g. `/var/lib/arangodb-apps`)
|
||||
* The app-path `<app-path>`: (e.g. `/var/lib/arangodb-apps`)
|
||||
* The selected database `<db>`: (e.g. `_system`)
|
||||
* The mount point `<mount>`: (e.g. `/example`)
|
||||
|
||||
Note: you can set your app-path to an arbitrary folder using the `--javascript.app-path` startup parameter.
|
||||
**Note**: You can set your app-path to an arbitrary folder using the `--javascript.app-path` startup parameter.
|
||||
Now the path is constructed as follows:
|
||||
|
||||
<app-path>/_db/<db>/<mount>/APP
|
||||
Linux: /var/lib/arangodb-apps/_db/_system/example/APP
|
||||
Mac: /usr/local/var/lib/arangodb-apps/_db/_system/example/APP
|
||||
Windows: C:\Program Files\ArangoDB\js\apps\_db\_system\example\APP
|
||||
```
|
||||
<app-path>/_db/<db>/<mount>/APP
|
||||
Linux: /var/lib/arangodb-apps/_db/_system/example/APP
|
||||
Mac: /usr/local/var/lib/arangodb-apps/_db/_system/example/APP
|
||||
Windows: C:\Program Files\ArangoDB\js\apps\_db\_system\example\APP
|
||||
```
|
||||
|
||||
<div class="versionDifference">
|
||||
Before 2.5 the folder was constructed using application name and version.
|
||||
That was necessary because installation was a two step process:
|
||||
|
||||
<!-- <div class="versionDifference"-->
|
||||
1. Including the Application sources into ArangoDB (and creating the folder)
|
||||
2. Mounting the application to one specific mountpoint.
|
||||
2. Mounting the application to one specific mountpoint
|
||||
|
||||
This caused some confusion and a lot of unnecessary administration overhead.
|
||||
One had to remember which apps are just known to ArangoDB, which ones are actually executed in which version etc.
|
||||
The use-case we actually introduced this staging for was heavy reuse of equal apps.
|
||||
However it turned out that this is rarely the case and the overhead by having redundant sources is small compared to the improved user experience not having this staging.
|
||||
So we decided to entirely remove the staging and make installation a one step process without caching old versions of an app.
|
||||
This means if you now *uninstall* an application it is removed from file system.
|
||||
Before 2.5 you had to *purge* the application to make sure it is removed.
|
||||
</div>
|
||||
So we decided to entirely remove the staging and make installation an one step process without caching old versions of an app.
|
||||
This means if you now **uninstall** an application it is removed from file system.
|
||||
Before 2.5 you had to **purge** the application to make sure it is removed.
|
||||
<!-- </div> -->
|
||||
|
||||
Now you can start modifying the files located there. As a good entry you should start with the [Controller](Controller.md)
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
!CHAPTER The Manifest File
|
||||
|
||||
In the *manifest.json* you define the components of your application.
|
||||
In the **manifest.json** you define the components of your application.
|
||||
The content is a JSON object with the following attributes (not all
|
||||
attributes are required though):
|
||||
|
||||
* *assets*: Deliver pre-processed files
|
||||
* *author*: The author name
|
||||
* *contributors*: An array containing objects, each represents a contributor (with *name* and optional *email*)
|
||||
* *controllers*: Map routes to FoxxControllers
|
||||
* *exports*: Map names to Foxx exports
|
||||
* *defaultDocument*: The default document when the applicated root (*/*) is called (defaults to *index.html*)
|
||||
* *description*: A short description of the application (Meta information)
|
||||
* *engines*: Should be an object with *arangodb* set to the ArangoDB version your Foxx app is compatible with.
|
||||
* *files*: Deliver files
|
||||
* *isSystem*: Mark an application as a system application
|
||||
* *keywords*: An array of keywords to help people find your Foxx app
|
||||
* *lib*: Base path for all required modules
|
||||
* *license*: Short form of the license (MIT, GPL...)
|
||||
* *name*: Name of the application (Meta information)
|
||||
* *repository*: An object with information about where you can find the repository: *type* and *url*
|
||||
* *setup*: Path to a setup script
|
||||
* *teardown*: Path to a teardown script
|
||||
* *thumbnail*: Path to a thumbnail that represents the application (Meta information)
|
||||
* *version*: Current version of the application (Meta information)
|
||||
* **assets**: Deliver preprocessed files
|
||||
* **author**: The author name
|
||||
* **contributors**: An array containing objects, each represents a contributor (with **name** and optional **email**)
|
||||
* **controllers**: Map routes to FoxxControllers
|
||||
* **exports**: Map names to Foxx exports
|
||||
* **defaultDocument**: The default document when the applicated root (**/**) is called (defaults to **index.html**)
|
||||
* **description**: A short description of the application (Meta information)
|
||||
* **engines**: Should be an object with **arangodb** set to the ArangoDB version your Foxx app is compatible with
|
||||
* **files**: Deliver files
|
||||
* **isSystem**: Mark an application as a system application
|
||||
* **keywords**: An array of keywords to help people find your Foxx app
|
||||
* **lib**: Base path for all required modules
|
||||
* **license**: Short form of the license (MIT, GPL...)
|
||||
* **name**: Name of the application (Meta information)
|
||||
* **repository**: An object with information about where you can find the repository: **type** and **url**
|
||||
* **setup**: Path to a setup script
|
||||
* **teardown**: Path to a teardown script
|
||||
* **thumbnail**: Path to a thumbnail that represents the application (Meta information)
|
||||
* **version**: Current version of the application (Meta information)
|
||||
|
||||
If you install an application using the Foxx manager or are using the
|
||||
development mode, your manifest will be checked for completeness and common errors.
|
||||
|
@ -67,25 +67,25 @@ A more complete example for a Manifest file:
|
|||
|
||||
You can provide a path to a JavaScript file that prepares ArangoDB for your
|
||||
application (or respectively removes it entirely). These scripts have access to
|
||||
*appCollection* and *appCollectionName*. Use the *setup* script to create all
|
||||
**appCollection** and **appCollectionName**. Use the **setup** script to create all
|
||||
collections your application needs and fill them with initial data if you want
|
||||
to. Use the *teardown* script to remove all collections you have created.
|
||||
to. Use the **teardown** script to remove all collections you have created.
|
||||
|
||||
Note: the setup script is called on each request in the development mode.
|
||||
If your application needs to set up specific collections, you should always
|
||||
If your application needs to set up specific collections, you should always
|
||||
check in the setup script whether they are already there.
|
||||
|
||||
The teardown script is called when an application is uninstalled. It is good
|
||||
practice to drop any collections in the teardown script that the application used
|
||||
practice to drop any collections in the teardown script that the application used
|
||||
exclusively, but this is not enforced. Maybe there are reasons to keep application
|
||||
data even after removing an application. It's up to you to decide what to do.
|
||||
|
||||
!SUBSECTION controllers is an object that matches routes to files
|
||||
|
||||
* The *key* is the route you want to mount at
|
||||
* The **key** is the route you want to mount at
|
||||
|
||||
* The *value* is the path to the JavaScript file containing the
|
||||
*FoxxController* you want to mount
|
||||
* The **value** is the path to the JavaScript file containing the
|
||||
**FoxxController** you want to mount
|
||||
|
||||
You can add multiple controllers in one manifest this way.
|
||||
|
||||
|
@ -116,21 +116,21 @@ to the files they are composed of. Let's take the following example:
|
|||
}
|
||||
```
|
||||
|
||||
If a request is made to */application.js* (in development mode), the file
|
||||
array provided will be processed one element at a time. The elements are
|
||||
paths to files (with the option to use wildcards). The files will be
|
||||
If a request is made to **/application.js** (in development mode), the file
|
||||
array provided will be processed one element at a time. The elements are
|
||||
paths to files (with the option to use wildcards). The files will be
|
||||
concatenated and delivered as a single file.
|
||||
|
||||
The content-type (or mime type) of the HTTP response when requesting
|
||||
*application.js* is automatically determined by looking at the filename
|
||||
extension in the asset name (*application.js* in the above example).
|
||||
If the asset does not have a filename extension, the content-type is
|
||||
determined by looking at the filename extension of the first file in the
|
||||
*files* list. If no file extension can be determined, the asset will be
|
||||
delivered with a content-type of *text/plain*.
|
||||
The content-type (or mime type) of the HTTP response when requesting
|
||||
**application.js** is automatically determined by looking at the filename
|
||||
extension in the asset name (**application.js** in the above example).
|
||||
If the asset does not have a filename extension, the content-type is
|
||||
determined by looking at the filename extension of the first file in the
|
||||
**files** list. If no file extension can be determined, the asset will be
|
||||
delivered with a content-type of **text/plain**.
|
||||
|
||||
It is possible to explicitly override the content-type for an asset by
|
||||
setting the optional *contentType* attribute of an asset as follows:
|
||||
setting the optional **contentType** attribute of an asset as follows:
|
||||
|
||||
```js
|
||||
"assets": {
|
||||
|
@ -142,4 +142,4 @@ setting the optional *contentType* attribute of an asset as follows:
|
|||
"contentType": "text/javascript"
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
!CHAPTER Details on FoxxModel
|
||||
|
||||
The model doesn't know anything about the database. It is just a representation
|
||||
of the data as an JavaScript object. You can add and overwrite the methods of
|
||||
the prototype in your model prototype via the object you give to extend. In
|
||||
your model file, export the model as *model*.
|
||||
The model doesn't know anything about the database. It is just a representation
|
||||
of the data as an JavaScript object. You can add and overwrite the methods of
|
||||
the prototype in your model prototype via the object you give to extend. In
|
||||
your model file, export the model as **model**.
|
||||
|
||||
```js
|
||||
var Foxx = require("org/arangodb/foxx");
|
||||
|
@ -17,9 +17,9 @@ exports.model = TodoModel;
|
|||
A Foxx Model can be initialized with an object of attributes and their values.
|
||||
|
||||
There's also the possibility of annotation: If you extend the model with a
|
||||
*schema* property, the model's attributes will be validated against it.
|
||||
**schema** property, the model's attributes will be validated against it.
|
||||
|
||||
You can define attributes in the schema using the bundled *joi* library.
|
||||
You can define attributes in the schema using the bundled **joi** library.
|
||||
For more information on the syntax see [the official joi documentation](https://github.com/spumko/joi).
|
||||
|
||||
```js
|
||||
|
@ -38,10 +38,10 @@ exports.model = PersonModel;
|
|||
```
|
||||
|
||||
This has two effects: On the one hand it provides documentation. If you annotated
|
||||
your model, you can use it in the *bodyParam* method for documentation.
|
||||
your model, you can use it in the **bodyParam** method for documentation.
|
||||
On the other hand it will influence the behavior of the constructor: If you provide
|
||||
an object to the constructor, it will validate its attributes and set the special
|
||||
*errors* property. This is especially useful if you want to to initialize
|
||||
**errors** property. This is especially useful if you want to to initialize
|
||||
the Model from user input. On the other hand it will set the default value for all
|
||||
attributes that have not been set by hand. An example:
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ Query Builder query objects can be used in any function that would normally expe
|
|||
|
||||
For a full overview of the query builder API [see the project documentation](https://github.com/arangodb/aqbjs).
|
||||
|
||||
*Examples*
|
||||
**Examples**
|
||||
|
||||
```js
|
||||
var db = require('org/arangodb').db;
|
||||
|
@ -29,27 +29,27 @@ Creates a query function that performs the given query and returns the result.
|
|||
|
||||
The returned query function optionally takes an object as its argument. If an object is provided, its properties will be used as the query's bind parameters. Any additional arguments will be passed to the transform function (or dropped if no transform function is defined).
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *cfg*: an object with the following properties:
|
||||
* *query*: an AQL query string or an ArangoDB Query Builder query object.
|
||||
* *params* (optional): an array of parameter names.
|
||||
* *context* (optional): an *applicationContext*.
|
||||
* *model* (optional): a *Foxx.Model* that will be applied to the query results.
|
||||
* *defaults* (optional): default values for the query's bind parameters. These can be overridden by passing a value for the same name to the query function.
|
||||
* *transform* (optional): a function that will be applied to the return value.
|
||||
* **cfg**: an object with the following properties:
|
||||
* **query**: an AQL query string or an ArangoDB Query Builder query object.
|
||||
* **params** (optional): an array of parameter names.
|
||||
* **context** (optional): an **applicationContext**.
|
||||
* **model** (optional): a **Foxx.Model** that will be applied to the query results.
|
||||
* **defaults** (optional): default values for the query's bind parameters. These can be overridden by passing a value for the same name to the query function.
|
||||
* **transform** (optional): a function that will be applied to the return value.
|
||||
|
||||
If *cfg* is a string, it will be used as the value of *cfg.query* instead.
|
||||
If **cfg** is a string, it will be used as the value of **cfg.query** instead.
|
||||
|
||||
If a *context* is specified, the values of all collection bind parameters will be passed through the context's *collectionName* method.
|
||||
If a **context** is specified, the values of all collection bind parameters will be passed through the context's **collectionName** method.
|
||||
|
||||
Note that collection bind parameters in AQL need to be referenced with two at-signs instead of one, e.g. `@@myCollectionVar` and their parameter name needs to be prefixed with an at-sign as well, e.g. `{'@myCollectionVar': 'collection_name'}`.
|
||||
|
||||
If *params* is provided, the query function will accept positional arguments instead of an object. If *params* is a string, it will be treated as an array containing that string.
|
||||
If **params** is provided, the query function will accept positional arguments instead of an object. If **params** is a string, it will be treated as an array containing that string.
|
||||
|
||||
If both *model* and *transform* are provided, the *transform* function will be applied to the result array _after_ the results have been converted into model instances. The *transform* function is always passed the entire result array and its return value will be returned by the query function.
|
||||
If both *model*** and **transform** are provided, the **transform** function will be applied to the result array _after_ the results have been converted into model instances. The **transform** function is always passed the entire result array and its return value will be returned by the query function.
|
||||
|
||||
*Examples*
|
||||
**Examples**
|
||||
|
||||
Basic usage example:
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@ If you have never build a Foxx App, then you can make your own [first Foxx App](
|
|||
|
||||
Foxx allows defining job queues that let you perform slow or expensive actions asynchronously. These queues can be used to send e-mails, call external APIs or perform other actions that you do not want to perform directly or want to retry on failure.
|
||||
|
||||
For the low-level functionality see the section *Task Management* in the chapter *JavaScript Modules*.
|
||||
For the low-level functionality see the section **Task Management** in the chapter **JavaScript Modules**.
|
||||
|
||||
*Examples*
|
||||
**Examples**
|
||||
|
||||
The following Foxx route handler will enqueue a job whenever the *"/log"* route is accessed that prints "Hello World!" to the server log.
|
||||
The following Foxx route handler will enqueue a job whenever the **"/log"** route is accessed that prints "Hello World!" to the server log.
|
||||
|
||||
```js
|
||||
var Foxx = require("org/arangodb/foxx");
|
||||
|
@ -30,14 +30,14 @@ Creates a queue with the given name and maximum number of workers.
|
|||
|
||||
`Foxx.queues.create(name, [maxWorkers])`
|
||||
|
||||
Returns the *Queue* instance for the given *name*. If the queue does not exist, a new queue with the given *name* will be created. If a queue with the given *name* already exists and *maxWorkers* is set, the queue's maximum number of workers will be updated.
|
||||
Returns the **Queue** instance for the given **name**. If the queue does not exist, a new queue with the given **name** will be created. If a queue with the given **name** already exists and **maxWorkers** is set, the queue's maximum number of workers will be updated.
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *name*: the name of the queue to create.
|
||||
* *maxWorkers* (optional): the maximum number of workers. Default: *1*.
|
||||
* **name**: the name of the queue to create
|
||||
* **maxWorkers** (optional): the maximum number of workers. Default: **1**
|
||||
|
||||
*Examples*
|
||||
**Examples**
|
||||
|
||||
```js
|
||||
// Create a queue with the default number of workers (i.e. one)
|
||||
|
@ -56,15 +56,15 @@ Fetches a queue with the given name.
|
|||
|
||||
`Foxx.queues.get(name)`
|
||||
|
||||
Returns the *Queue* instance for the given *name*. If the queue does not exist, an exception is thrown instead.
|
||||
Returns the **Queue** instance for the given **name**. If the queue does not exist an exception is thrown instead.
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *name*: the name of the queue to fetch.
|
||||
* **name**: the name of the queue to fetch
|
||||
|
||||
*Examples*
|
||||
**Examples**
|
||||
|
||||
If the queue does not yet exist, an exception is thrown:
|
||||
If the queue does not yet exist an exception is thrown:
|
||||
|
||||
```js
|
||||
Foxx.queues.get("some-queue");
|
||||
|
@ -72,7 +72,7 @@ Foxx.queues.get("some-queue");
|
|||
// at ...
|
||||
```
|
||||
|
||||
Otherwise, the *Queue* instance will be returned:
|
||||
Otherwise the **Queue** instance will be returned:
|
||||
|
||||
```js
|
||||
var queue1 = Foxx.queues.create("some-queue");
|
||||
|
@ -86,17 +86,17 @@ Deletes the queue with the given name from the database.
|
|||
|
||||
`Foxx.queues.delete(name)`
|
||||
|
||||
Returns *true* if the queue was deleted successfully. If the queue did not exist, it returns *false* instead.
|
||||
Returns **true** if the queue was deleted successfully. If the queue did not exist, it returns **false** instead.
|
||||
|
||||
When a queue is deleted, jobs on that queue will no longer be executed.
|
||||
|
||||
Deleting a queue will not delete any jobs on that queue.
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *name*: the name of the queue to delete.
|
||||
* **name**: the name of the queue to delete
|
||||
|
||||
*Examples*
|
||||
**Examples**
|
||||
|
||||
```js
|
||||
var queue = Foxx.queues.create("my-queue");
|
||||
|
@ -110,19 +110,19 @@ Registers a job type with the queue manager.
|
|||
|
||||
`Foxx.queues.registerJobType(name, opts)`
|
||||
|
||||
If *opts* is a function, it will be treated as the *execute* function.
|
||||
If **opts** is a function it will be treated as the **execute** function.
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *name*: the name of the job type to register.
|
||||
* *opts*: an object with the following properties:
|
||||
* *execute*: a function to pass the job data to when a job is executed.
|
||||
* *maxFailures* (optional): the number of times a job will be re-tried before it is marked as *"failed"*. A negative value or *Infinity* means that the job will be re-tried on failure indefinitely. Default: *0*.
|
||||
* *schema* (optional): a [Joi](https://github.com/hapijs/joi) schema to validate a job's data against before accepting it.
|
||||
* *preprocess* (optional): a function to pre-process a job's (validated) data before serializing it in the queue.
|
||||
* *backOff* (optional): either a function that takes the number of times the job has failed before as input and returns the number of milliseconds to wait before trying the job again, or the delay to be used to calculate an [exponential back-off](https://en.wikipedia.org/wiki/Exponential_backoff), or *0* for no delay. Default: *1000*.
|
||||
* **name**: the name of the job type to register
|
||||
* **opts**: an object with the following properties:
|
||||
* **execute**: a function to pass the job data to when a job is executed
|
||||
* **maxFailures** (optional): the number of times a job will be re-tried before it is marked as **"failed"**. A negative value or **Infinity** means that the job will be re-tried on failure indefinitely. Default: **0**
|
||||
* **schema** (optional): a [Joi](https://github.com/hapijs/joi) schema to validate a job's data against before accepting it
|
||||
* **preprocess** (optional): a function to pre-process a job's (validated) data before serializing it in the queue
|
||||
* **backOff** (optional): either a function that takes the number of times the job has failed before as input and returns the number of milliseconds to wait before trying the job again, or the delay to be used to calculate an [exponential back-off](https://en.wikipedia.org/wiki/Exponential_backoff), or **0** for no delay. Default: **1000**
|
||||
|
||||
*Examples*
|
||||
**Examples**
|
||||
|
||||
```js
|
||||
var Foxx = require("org/arangodb/foxx");
|
||||
|
@ -139,18 +139,18 @@ Adds a job of the given type to the given queue.
|
|||
|
||||
Returns the job id.
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *name*: the name of the job's job type.
|
||||
* *data*: the job data of the job; must be serializable to JSON.
|
||||
* *opts* (optional): an object with any of the following properties:
|
||||
* *success* (optional): a function to be called after the job has been completed successfully.
|
||||
* *failure* (optional): a function to be called after the job has failed too many times.
|
||||
* *delayUntil* (optional): a timestamp in milliseconds until which the execution of the job should be delayed. Default: *Date.now()*.
|
||||
* *backOff* (optional): either a function that takes the number of times the job has failed before as input and returns the number of milliseconds to wait before trying the job again, or the delay to be used to calculate an [exponential back-off](https://en.wikipedia.org/wiki/Exponential_backoff), or *0* for no delay. See [Registering a job type](#registering-a-job-type).
|
||||
* *allowUnknown* (optional): whether the job should be queued even if the job type name does not match a currently registered job type. Default: *false*.
|
||||
* *maxFailures* (optional): the number of times the job will be re-tried before it is marked as *"failed"*. A negative value or *Infinity* means that the job will be re-tried on failure indefinitely. See [Registering a job type](#registering-a-job-type).
|
||||
Note that if you pass a function for the *backOff* calculation, *success* callback or *failure* callback options the function must not rely on any external scope or external variables.
|
||||
* **name**: the name of the job's job type
|
||||
* **data**: the job data of the job; must be serializable to JSON
|
||||
* **opts** (optional): an object with any of the following properties:
|
||||
* **success** (optional): a function to be called after the job has been completed successfully
|
||||
* **failure** (optional): a function to be called after the job has failed too many times
|
||||
* **delayUntil** (optional): a timestamp in milliseconds until which the execution of the job should be delayed. Default: **Date.now()**
|
||||
* **backOff** (optional): either a function that takes the number of times the job has failed before as input and returns the number of milliseconds to wait before trying the job again, or the delay to be used to calculate an [exponential back-off](https://en.wikipedia.org/wiki/Exponential_backoff), or **0** for no delay. See [Registering a job type](#registering-a-job-type)
|
||||
* **allowUnknown** (optional): whether the job should be queued even if the job type name does not match a currently registered job type. Default: **false**
|
||||
* **maxFailures** (optional): the number of times the job will be re-tried before it is marked as *"*failed*"*. A negative value or **Infinity** means that the job will be re-tried on failure indefinitely. See [Registering a job type](#registering-a-job-type)
|
||||
Note that if you pass a function for the **backOff** calculation, **success** callback or **failure** callback options the function must not rely on any external scope or external variables.
|
||||
|
||||
*Examples*
|
||||
|
||||
|
@ -162,7 +162,7 @@ var queue = Foxx.queues.create("my-queue");
|
|||
queue.push("log", "Hello World!");
|
||||
```
|
||||
|
||||
This will **not** work, because *console* was defined outside the callback function:
|
||||
This will **not** work, because **console** was defined outside the callback function:
|
||||
|
||||
```js
|
||||
var Foxx = require("org/arangodb/foxx");
|
||||
|
@ -181,13 +181,13 @@ Creates a proxy object representing a job with the given job id.
|
|||
|
||||
`Queue::get(jobId)`
|
||||
|
||||
Returns the *Job* instance for the given *jobId*. Properties of the job object will be fetched whenever they are referenced and can not be modified.
|
||||
Returns the **Job** instance for the given **jobId**. Properties of the job object will be fetched whenever they are referenced and can not be modified.
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *jobId*: the id of the job to create a proxy object for.
|
||||
* **jobId**: the id of the job to create a proxy object for.
|
||||
|
||||
*Examples*
|
||||
**Examples**
|
||||
```js
|
||||
var jobId = queue.push("log", "Hello World!");
|
||||
var job = queue.get(jobId);
|
||||
|
@ -200,11 +200,11 @@ Deletes a job with the given job id.
|
|||
|
||||
`Queue::delete(jobId)`
|
||||
|
||||
Returns *true* if the job was deleted successfully. If the job did not exist, it returns *false* instead.
|
||||
Returns **true** if the job was deleted successfully. If the job did not exist it returns **false** instead.
|
||||
|
||||
!SECTION Fetching an arry of jobs in a queue
|
||||
!SECTION Fetching an array of jobs in a queue
|
||||
|
||||
*Examples*
|
||||
**Examples**
|
||||
|
||||
```js
|
||||
queue.push("log", "Hello World!", {delayUntil: Date.now() + 50});
|
||||
|
@ -221,41 +221,41 @@ assertEqual(queue.complete("log").length, 1);
|
|||
|
||||
`Queue::pending([type])`
|
||||
|
||||
Returns an array of job ids of jobs in the given queue with the status *"pending"*, optionally filtered by the given job type.
|
||||
Returns an array of job ids of jobs in the given queue with the status **"pending"**, optionally filtered by the given job type.
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *type* (optional): the name of the job type to filter the results.
|
||||
* **type** (optional): the name of the job type to filter the results
|
||||
|
||||
!SUBSECTION Fetching an array of jobs that are currently in progress
|
||||
|
||||
`Queue::progress([type])`
|
||||
|
||||
Returns an array of job ids of jobs in the given queue with the status *"progress"*, optionally filtered by the given job type.
|
||||
Returns an array of job ids of jobs in the given queue with the status **"progress"**, optionally filtered by the given job type.
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *type* (optional): the name of the job type to filter the results.
|
||||
* **type** (optional): the name of the job type to filter the results
|
||||
|
||||
!SUBSECTION Fetching an array of completed jobs in a queue
|
||||
|
||||
`Queue::complete([type])`
|
||||
|
||||
Returns an array of job ids of jobs in the given queue with the status *"complete"*, optionally filtered by the given job type.
|
||||
Returns an array of job ids of jobs in the given queue with the status **"complete"**, optionally filtered by the given job type.
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *type* (optional): the name of the job type to filter the results.
|
||||
* **type** (optional): the name of the job type to filter the results.
|
||||
|
||||
!SUBSECTION Fetching an array of failed jobs in a queue
|
||||
|
||||
`Queue::failed([type])`
|
||||
|
||||
Returns an array of job ids of jobs in the given queue with the status *"failed"*, optionally filtered by the given job type.
|
||||
Returns an array of job ids of jobs in the given queue with the status **"failed"**, optionally filtered by the given job type.
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *type* (optional): the name of the job type to filter the results.
|
||||
* **type** (optional): the name of the job type to filter the results.
|
||||
|
||||
!SUBSECTION Fetching an array of all jobs in a queue
|
||||
|
||||
|
@ -263,9 +263,9 @@ Returns an array of job ids of jobs in the given queue with the status *"failed"
|
|||
|
||||
Returns an array of job ids of all jobs in the given queue, optionally filtered by the given job type.
|
||||
|
||||
*Parameter*
|
||||
**Parameter**
|
||||
|
||||
* *type* (optional): the name of the job type to filter the results.
|
||||
* **type** (optional): the name of the job type to filter the results.
|
||||
|
||||
!SECTION Aborting a job
|
||||
|
||||
|
@ -273,5 +273,5 @@ Aborts a non-completed job.
|
|||
|
||||
`Job::abort()`
|
||||
|
||||
Sets a job's status to *"failed"* if it is not already *"complete"*, without calling the job's *onFailure* callback.
|
||||
Sets a job's status to **"failed"** if it is not already **"complete"**, without calling the job's **onFailure** callback.
|
||||
|
||||
|
|
|
@ -1,38 +1,38 @@
|
|||
!CHAPTER Develop your own foxx
|
||||
!CHAPTER Develop your own Foxx
|
||||
|
||||
This chapter will explain to you how to write a foxx on your own and use it to enhance the ArangoDBs functionality.
|
||||
This chapter will explain to you how to write a Foxx on your own and use it to enhance the ArangoDB's functionality.
|
||||
Be it a microservice, an API with a user interface or an internal library.
|
||||
|
||||
Before reading this chapter you should make sure to at least read one of the install sections beforehand to get a good staring point.
|
||||
Recommended is the [generate](../Install/Generate.md) section to get started with your own foxx, but you can also start with an existing one.
|
||||
Recommended is the [generate](../Install/Generate.md) section to get started with your own Foxx, but you can also start with an existing one.
|
||||
|
||||
At first we will introduce the development mode and describe it's side effects.
|
||||
You can skip this section if you do not have access to the filesystem of ArangoDB as you will not get the benefits of this mode.
|
||||
At first we will introduce the development mode and describe its side effects.
|
||||
You can skip this section if you do not have access to the file system of ArangoDB as you will not get the benefits of this mode.
|
||||
You will have to stick to the procedure described in [New Versions](../Production/Upgrade.md).
|
||||
|
||||
[Read More](Developmentmode.md)
|
||||
|
||||
Next you will learn about the debugging mechanisms if you have set a foxx into development mode.
|
||||
Next you will learn about the debugging mechanisms if you have set a Foxx into development mode.
|
||||
The app will return more debugging information in this mode like stacktraces.
|
||||
In production mode stacktraces will be kept internally.
|
||||
|
||||
[Read More](Debugging.md)
|
||||
|
||||
If you want to get started with coding this is the section to start with.
|
||||
If you want to get started with coding this is the section to begin with.
|
||||
It will introduce the folder structure and describes where which files have to be located on server side.
|
||||
|
||||
[Read More](Folder.md)
|
||||
|
||||
Now we are entering the reference documentation of tools available in the foxx framework.
|
||||
Now we are entering the reference documentation of tools available in the Foxx framework.
|
||||
The tools contain:
|
||||
|
||||
* [Controller](Foxx/Develop/Controller.md)
|
||||
* [Setup & Teardown](Foxx/Develop/Scripts.md)
|
||||
* [Repository](Foxx/Develop/Repository.md)
|
||||
* [Model](Foxx/Develop/Model.md)
|
||||
* [Queries](Foxx/Develop/Queries.md)
|
||||
* [Background Tasks](Foxx/Develop/Queues.md)
|
||||
* [Console API](Foxx/FoxxConsole.md)
|
||||
* [Controller](../Develop/Controller.md)
|
||||
* [Setup & Teardown](../Develop/Scripts.md)
|
||||
* [Repository](../Develop/Repository.md)
|
||||
* [Model](../Develop/Model.md)
|
||||
* [Queries](../Develop/Queries.md)
|
||||
* [Background Tasks](../Develop/Queues.md)
|
||||
* [Console API](../Develop/Console.md)
|
||||
|
||||
Finally we want to apply some meta information to the foxx.
|
||||
How this is done is described in the [Metainformation](Foxx/Develop/Manifest.md) chapter.
|
||||
Finally we want to apply some meta information to the Foxx.
|
||||
How this is done is described in the [Metainformation](../Develop/Manifest.md) chapter.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
!CHAPTER Details on FoxxRepository
|
||||
|
||||
A repository is a gateway to the database. It gets data from the database, updates it or saves new data. It uses the given model when it returns a model and expects instances of the model for methods like save. In your repository file, export the repository as *repository*.
|
||||
A repository is a gateway to the database. It gets data from the database, updates it or saves new data. It uses the given model when it returns a model and expects instances of the model for methods like save. In your repository file, export the repository as **repository**.
|
||||
|
||||
```javascript
|
||||
var Foxx = require("org/arangodb/foxx");
|
||||
|
@ -21,7 +21,7 @@ You can define custom query methods using Foxx.createQuery and Foxx.Repository.e
|
|||
|
||||
For more details see the chapter on [Foxx Queries](../Foxx/FoxxQueries.md).
|
||||
|
||||
*Examples*
|
||||
**Examples**
|
||||
|
||||
Making a simple query in the repository and using it from the controller:
|
||||
|
||||
|
@ -103,7 +103,7 @@ ctrl.get("/:id", function(req, res) {
|
|||
|
||||
Repository can take care of ensuring the existence of collection indexes for you.
|
||||
If you define indexes for a repository, instances of the repository will have
|
||||
access to additional index-specific methods like *range* or *fulltext* (see below).
|
||||
access to additional index-specific methods like **range** or **fulltext** (see below).
|
||||
|
||||
The syntax for defining indexes is the same used in [*collection.ensureIndex*](../IndexHandling/README.md).
|
||||
|
||||
|
|
|
@ -5,53 +5,60 @@ These scripts are used to create or drop collections, create indexes or insert s
|
|||
|
||||
!SECTION Setup script
|
||||
|
||||
The setup script will be executed during the install process of your foxx.
|
||||
The setup script will be executed during the install process of your Foxx.
|
||||
|
||||
unix>foxx-manager install hello-foxx /example
|
||||
```
|
||||
unix>foxx-manager install hello-foxx /example
|
||||
```
|
||||
|
||||
It is typically used to setup collections, insert some seed data or create default user accounts.
|
||||
As one example for a setup script we can take a look at the one given with hello-foxx:
|
||||
|
||||
var console = require("console");
|
||||
var arangodb = require("org/arangodb");
|
||||
var db = arangodb.db;
|
||||
```
|
||||
var console = require("console");
|
||||
var arangodb = require("org/arangodb");
|
||||
var db = arangodb.db;
|
||||
|
||||
var texts = applicationContext.collectionName("texts");
|
||||
var texts = applicationContext.collectionName("texts");
|
||||
|
||||
if (db._collection(texts) === null) {
|
||||
var collection = db._create(texts);
|
||||
if (db._collection(texts) === null) {
|
||||
var collection = db._create(texts);
|
||||
|
||||
collection.save({ text: "entry 1 from collection texts" });
|
||||
collection.save({ text: "entry 2 from collection texts" });
|
||||
collection.save({ text: "entry 3 from collection texts" });
|
||||
}
|
||||
else {
|
||||
console.log("collection '%s' already exists. Leaving it untouched.", texts);
|
||||
}
|
||||
collection.save({ text: "entry 1 from collection texts" });
|
||||
collection.save({ text: "entry 2 from collection texts" });
|
||||
collection.save({ text: "entry 3 from collection texts" });
|
||||
}
|
||||
else {
|
||||
console.log("collection '%s' already exists. Leaving it untouched.", texts);
|
||||
}
|
||||
```
|
||||
|
||||
It first creates the collection texts, specific for this application and inserts three default documents.
|
||||
|
||||
!SECTION Teardown script
|
||||
|
||||
The teardown script will be executed during the uninstall process of your foxx.
|
||||
The teardown script will be executed during the uninstall process of your Foxx.
|
||||
|
||||
```
|
||||
unix>foxx-manager uninstall /example
|
||||
````
|
||||
|
||||
unix>foxx-manager uninstall /example
|
||||
|
||||
This one is typically used to erase the data collected with the foxx.
|
||||
ArangoDB will never automatically delete collections attached to a foxx unless they are dropped in the teardown script.
|
||||
This one is typically used to erase the data collected with the Foxx.
|
||||
ArangoDB will never automatically delete collections attached to a Foxx unless they are dropped in the teardown script.
|
||||
So if you want to keep your data simply do not drop the collections here.
|
||||
As an example for a typical teardown script we can again take a look at the hello-foxx example:
|
||||
|
||||
var arangodb = require("org/arangodb");
|
||||
var db = arangodb.db;
|
||||
```
|
||||
var arangodb = require("org/arangodb");
|
||||
var db = arangodb.db;
|
||||
|
||||
var texts = applicationContext.collectionName("texts");
|
||||
var collection = db._collection(texts);
|
||||
var texts = applicationContext.collectionName("texts");
|
||||
var collection = db._collection(texts);
|
||||
|
||||
if (collection !== null) {
|
||||
collection.drop();
|
||||
}
|
||||
```
|
||||
|
||||
It drops the collection unless it has not yet been dropped.
|
||||
|
||||
|
@ -60,13 +67,15 @@ It drops the collection unless it has not yet been dropped.
|
|||
In order to activate the scripts you have to define them inside the manifest, similar to controllers.
|
||||
So your manifest will look like this:
|
||||
|
||||
{
|
||||
"name": "hello-foxx",
|
||||
"version": "1.4.4",
|
||||
"controllers": {},
|
||||
"setup": "scripts/setup.js",
|
||||
"teardown": "scripts/teardown.js"
|
||||
}
|
||||
```
|
||||
{
|
||||
"name": "hello-foxx",
|
||||
"version": "1.4.4",
|
||||
"controllers": {},
|
||||
"setup": "scripts/setup.js",
|
||||
"teardown": "scripts/teardown.js"
|
||||
}
|
||||
```
|
||||
|
||||
Keep in mind that all scripts are optional and can be omitted.
|
||||
It is only possible to define one script of each type.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
!CHAPTER Generate a new Application
|
||||
|
||||
In this chapter we will make use of the foxx manager as described [before](README.md).
|
||||
This time we do not have anything to start from and would like ArangoDB create a template for us.
|
||||
In this chapter we will make use of the Foxx manager as described [before](README.md).
|
||||
This time we do not have anything to start from and would like ArangoDB to create a template for us.
|
||||
For a generated application you only need to be prepared to answer some questions for meta information, don't worry if you do not yet have an answer, all of this info is optional and can be inserted later:
|
||||
|
||||
* Your name (e.g. `Author`)
|
||||
|
@ -12,30 +12,38 @@ For a generated application you only need to be prepared to answer some question
|
|||
|
||||
Now you can create a new empty application with just one line:
|
||||
|
||||
```
|
||||
unix> foxx-manager install EMPTY /example '{"author": "Author", "name": "MyApp", "description": "An application to access ArangoDB", "license": "Apache 2", "collectionNames": ["MyCollection"]}'
|
||||
Application MyApp version 0.0.1 installed successfully at mount point /example
|
||||
options used: {"author":"Author","name":"MyApp","description":"An application to access ArangoDB","license":"Apache 2","collectionNames":["MyCollection"],"configuration":{}
|
||||
options used: {"author":"Author","name":"MyApp","description":"An application to access ArangoDB","license":"Apache 2","collectionNames":["MyCollection"],"configuration":{} }
|
||||
```
|
||||
|
||||
This action now has generated you a fresh application in version 0.0.1.
|
||||
It has setup all meta-information you have provided
|
||||
It has set up all meta-information you have provided
|
||||
For each collection in `collectionNames` it has created a collection and generated all 5 CRUD routes: List all, Create one, Read one, Update one, Delete one.
|
||||
|
||||
You can use the generator in all functions of the foxx-manager that allow to install foxx applications:
|
||||
You can use the generator in all functions of the Foxx-manager that allows to install Foxx applications:
|
||||
|
||||
*install*
|
||||
**install**
|
||||
|
||||
unix> foxx-manager install EMPTY /example '{"author": "Author", "name": "MyApp", "description": "An application to access ArangoDB", "license": "Apache 2", "collectionNames": ["MyCollection"]}'
|
||||
Application MyApp version 0.0.1 installed successfully at mount point /example
|
||||
options used: {"author":"Author","name":"MyApp","description":"An application to access ArangoDB","license":"Apache 2","collectionNames":["MyCollection"],"configuration":{}
|
||||
```
|
||||
unix> foxx-manager install EMPTY /example '{"author": "Author", "name": "MyApp", "description": "An application to access ArangoDB", "license": "Apache 2", "collectionNames": ["MyCollection"]}'
|
||||
Application MyApp version 0.0.1 installed successfully at mount point /example
|
||||
options used: {"author":"Author","name":"MyApp","description":"An application to access ArangoDB","license":"Apache 2","collectionNames":["MyCollection"],"configuration":{} }
|
||||
```
|
||||
|
||||
*replace*
|
||||
**replace**
|
||||
|
||||
unix> foxx-manager replace EMPTY /example '{"author": "Author", "name": "MyApp", "description": "An application to access ArangoDB", "license": "Apache 2", "collectionNames": ["MyCollection"]}'
|
||||
Application MyApp version 0.0.1 installed successfully at mount point /example
|
||||
options used: {"author":"Author","name":"MyApp","description":"An application to access ArangoDB","license":"Apache 2","collectionNames":["MyCollection"],"configuration":{}
|
||||
```
|
||||
unix> foxx-manager replace EMPTY /example '{"author": "Author", "name": "MyApp", "description": "An application to access ArangoDB", "license": "Apache 2", "collectionNames": ["MyCollection"]}'
|
||||
Application MyApp version 0.0.1 installed successfully at mount point /example
|
||||
options used: {"author":"Author","name":"MyApp","description":"An application to access ArangoDB","license":"Apache 2","collectionNames":["MyCollection"],"configuration":{} }
|
||||
```
|
||||
|
||||
*upgrade*
|
||||
**upgrade**
|
||||
|
||||
unix> foxx-manager upgrade EMPTY /example '{"author": "Author", "name": "MyApp", "description": "An application to access ArangoDB", "license": "Apache 2", "collectionNames": ["MyCollection"]}'
|
||||
Application MyApp version 0.0.1 installed successfully at mount point /example
|
||||
options used: {"author":"Author","name":"MyApp","description":"An application to access ArangoDB","license":"Apache 2","collectionNames":["MyCollection"],"configuration":{}
|
||||
```
|
||||
unix> foxx-manager upgrade EMPTY /example '{"author": "Author", "name": "MyApp", "description": "An application to access ArangoDB", "license": "Apache 2", "collectionNames": ["MyCollection"]}'
|
||||
Application MyApp version 0.0.1 installed successfully at mount point /example
|
||||
options used: {"author":"Author","name":"MyApp","description":"An application to access ArangoDB","license":"Apache 2","collectionNames":["MyCollection"],"configuration":{} }
|
||||
```
|
||||
|
|
|
@ -1,40 +1,50 @@
|
|||
!CHAPTER Install Applications from github
|
||||
|
||||
In this chapter we will make use of the foxx manager as described [before](README.md).
|
||||
In this chapter we will make use of the Foxx manager as described [before](README.md).
|
||||
This time we want to install an app out of our version control hosted on [github.com](https://www.github.com).
|
||||
|
||||
In order to install an application we need three informations:
|
||||
|
||||
* *Repository*: The name of the repository.
|
||||
* *Username*: The username of the user owning the repository.
|
||||
* *Version*: (optional) branch or tag available on the repository.
|
||||
* **Repository**: The name of the repository.
|
||||
* **Username**: The username of the user owning the repository.
|
||||
* **Version**: (optional) branch or tag available on the repository.
|
||||
|
||||
As an example, we would like to install [www.github.com/arangodb/hello-foxx](https://www.github.com/arangodb/hello-foxx).
|
||||
The *username* is *arangodb*, the *repository* is *hello-foxx*.
|
||||
If we do not define a *version* it will automatically install the master branch.
|
||||
The **username** is **arangodb**, the **repository** is **hello-foxx**.
|
||||
If we do not define a **version** it will automatically install the master branch.
|
||||
|
||||
unix> foxx-manager install git:arangodb/hello-foxx /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
```
|
||||
unix> foxx-manager install git:arangodb/hello-foxx /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
```
|
||||
|
||||
The hello-foxx app has defined a tag for version 1.4.4 that is named "v1.4.4".
|
||||
We can simply append this tag in the install command:
|
||||
|
||||
unix> foxx-manager install git:arangodb/hello-foxx:v1.4.4 /legacy
|
||||
Application hello-foxx version 1.4.4 installed successfully at mount point /legacy
|
||||
```
|
||||
unix> foxx-manager install git:arangodb/hello-foxx:v1.4.4 /legacy
|
||||
Application hello-foxx version 1.4.4 installed successfully at mount point /legacy
|
||||
```
|
||||
|
||||
This reference for github repositories can be used in all functions of the foxx-manager that allow to install foxx applications:
|
||||
This reference for github repositories can be used in all functions of the Foxx-manager that allow to install Foxx applications:
|
||||
|
||||
*install*
|
||||
**install**
|
||||
|
||||
unix> foxx-manager install git:arangodb/hello-foxx:v1.4.4 /legacy
|
||||
Application hello-foxx version 1.4.4 installed successfully at mount point /legacy
|
||||
```
|
||||
unix> foxx-manager install git:arangodb/hello-foxx:v1.4.4 /legacy
|
||||
Application hello-foxx version 1.4.4 installed successfully at mount point /legacy
|
||||
```
|
||||
|
||||
*replace*
|
||||
**replace**
|
||||
|
||||
unix> foxx-manager replace git:arangodb/hello-foxx:v1.4.4 /legacy
|
||||
Application hello-foxx version 1.4.4 installed successfully at mount point /legacy
|
||||
```
|
||||
unix> foxx-manager replace git:arangodb/hello-foxx:v1.4.4 /legacy
|
||||
Application hello-foxx version 1.4.4 installed successfully at mount point /legacy
|
||||
```
|
||||
|
||||
*upgrade*
|
||||
**upgrade**
|
||||
|
||||
unix> foxx-manager upgrade git:arangodb/hello-foxx:v1.5.0 /legacy
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /legacy
|
||||
```
|
||||
unix> foxx-manager upgrade git:arangodb/hello-foxx:v1.5.0 /legacy
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /legacy
|
||||
```
|
||||
|
|
|
@ -1,86 +1,96 @@
|
|||
!CHAPTER Install Applications from local file system
|
||||
|
||||
In this chapter we will make use of the foxx manager as described [before](README.md).
|
||||
In this chapter we will make use of the Foxx manager as described [before](README.md).
|
||||
This time we want to install an app that is located on our local file system.
|
||||
At this point we have to mention that it if you connect to a remote ArangoDB with
|
||||
At this point we have to mention that it if you connect to a remote ArangoDB with
|
||||
|
||||
unix> foxx-manager --server.endpoint tcp://example.com:8529
|
||||
```
|
||||
unix> foxx-manager --server.endpoint tcp://example.com:8529
|
||||
```
|
||||
|
||||
the file has to be available on your local machine, not on the remote server.
|
||||
The file has to be available on your local machine, not on the remote server.
|
||||
The only thing you need is the path to your application either relative or absolute.
|
||||
You can install a foxx application right from a directory:
|
||||
You can install a Foxx application right from a directory:
|
||||
|
||||
unix> ls /Users/arangodb/hello-foxx
|
||||
README.md app.js assets files kaffee.coffee lib
|
||||
manifest.json models scripts thumbnail.png
|
||||
unix> foxx-manager install /Users/arangodb/hello-foxx /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
```
|
||||
unix> ls /Users/arangodb/hello-foxx
|
||||
README.md app.js assets files kaffee.coffee lib
|
||||
manifest.json models scripts thumbnail.png
|
||||
unix> foxx-manager install /Users/arangodb/hello-foxx /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
```
|
||||
|
||||
Or you can pack the application into a zip archive.
|
||||
And then install using this archive.
|
||||
|
||||
```
|
||||
unix> unzip -l ../hello-foxx.zip
|
||||
Archive: hello-foxx.zip
|
||||
0836dc2e81be8264e480a7695b46c1abe7ef153d
|
||||
Length Date Time Name
|
||||
-------- ---- ---- ----
|
||||
0 09-10-14 15:35 hello-foxx/
|
||||
1256 09-10-14 15:35 hello-foxx/README.md
|
||||
11200 09-10-14 15:35 hello-foxx/app.js
|
||||
0 09-10-14 15:35 hello-foxx/assets/
|
||||
0 09-10-14 15:35 hello-foxx/assets/css/
|
||||
82 09-10-14 15:35 hello-foxx/assets/css/base.css
|
||||
86 09-10-14 15:35 hello-foxx/assets/css/custom.css
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/css/
|
||||
22111 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/css/bootstrap-responsive.css
|
||||
16849 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/css/bootstrap-responsive.min.css
|
||||
127247 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/css/bootstrap.css
|
||||
105939 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/css/bootstrap.min.css
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/img/
|
||||
8777 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/img/glyphicons-halflings-white.png
|
||||
12799 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/img/glyphicons-halflings.png
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/jquery/
|
||||
268380 09-10-14 15:35 hello-foxx/assets/vendor/jquery/jquery.js
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/sh/
|
||||
1981 09-10-14 15:35 hello-foxx/assets/vendor/sh/highlighter.css
|
||||
5563 09-10-14 15:35 hello-foxx/assets/vendor/sh/sh_javascript.js
|
||||
5305 09-10-14 15:35 hello-foxx/assets/vendor/sh/sh_main.min.js
|
||||
0 09-10-14 15:35 hello-foxx/files/
|
||||
3266 09-10-14 15:35 hello-foxx/files/index.html
|
||||
398 09-10-14 15:35 hello-foxx/files/static.html
|
||||
361 09-10-14 15:35 hello-foxx/kaffee.coffee
|
||||
0 09-10-14 15:35 hello-foxx/lib/
|
||||
108 09-10-14 15:35 hello-foxx/lib/a.js
|
||||
43 09-10-14 15:35 hello-foxx/lib/c.js
|
||||
1129 09-10-14 15:35 hello-foxx/manifest.json
|
||||
0 09-10-14 15:35 hello-foxx/models/
|
||||
330 09-10-14 15:35 hello-foxx/models/tiger.js
|
||||
0 09-10-14 15:35 hello-foxx/scripts/
|
||||
2065 09-10-14 15:35 hello-foxx/scripts/setup.js
|
||||
1798 09-10-14 15:35 hello-foxx/scripts/teardown.js
|
||||
17727 09-10-14 15:35 hello-foxx/thumbnail.png
|
||||
-------- -------
|
||||
614800 37 files
|
||||
|
||||
unix> unzip -l ../hello-foxx.zip
|
||||
Archive: hello-foxx.zip
|
||||
0836dc2e81be8264e480a7695b46c1abe7ef153d
|
||||
Length Date Time Name
|
||||
-------- ---- ---- ----
|
||||
0 09-10-14 15:35 hello-foxx/
|
||||
1256 09-10-14 15:35 hello-foxx/README.md
|
||||
11200 09-10-14 15:35 hello-foxx/app.js
|
||||
0 09-10-14 15:35 hello-foxx/assets/
|
||||
0 09-10-14 15:35 hello-foxx/assets/css/
|
||||
82 09-10-14 15:35 hello-foxx/assets/css/base.css
|
||||
86 09-10-14 15:35 hello-foxx/assets/css/custom.css
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/css/
|
||||
22111 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/css/bootstrap-responsive.css
|
||||
16849 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/css/bootstrap-responsive.min.css
|
||||
127247 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/css/bootstrap.css
|
||||
105939 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/css/bootstrap.min.css
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/img/
|
||||
8777 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/img/glyphicons-halflings-white.png
|
||||
12799 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/img/glyphicons-halflings.png
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/jquery/
|
||||
268380 09-10-14 15:35 hello-foxx/assets/vendor/jquery/jquery.js
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/sh/
|
||||
1981 09-10-14 15:35 hello-foxx/assets/vendor/sh/highlighter.css
|
||||
5563 09-10-14 15:35 hello-foxx/assets/vendor/sh/sh_javascript.js
|
||||
5305 09-10-14 15:35 hello-foxx/assets/vendor/sh/sh_main.min.js
|
||||
0 09-10-14 15:35 hello-foxx/files/
|
||||
3266 09-10-14 15:35 hello-foxx/files/index.html
|
||||
398 09-10-14 15:35 hello-foxx/files/static.html
|
||||
361 09-10-14 15:35 hello-foxx/kaffee.coffee
|
||||
0 09-10-14 15:35 hello-foxx/lib/
|
||||
108 09-10-14 15:35 hello-foxx/lib/a.js
|
||||
43 09-10-14 15:35 hello-foxx/lib/c.js
|
||||
1129 09-10-14 15:35 hello-foxx/manifest.json
|
||||
0 09-10-14 15:35 hello-foxx/models/
|
||||
330 09-10-14 15:35 hello-foxx/models/tiger.js
|
||||
0 09-10-14 15:35 hello-foxx/scripts/
|
||||
2065 09-10-14 15:35 hello-foxx/scripts/setup.js
|
||||
1798 09-10-14 15:35 hello-foxx/scripts/teardown.js
|
||||
17727 09-10-14 15:35 hello-foxx/thumbnail.png
|
||||
-------- -------
|
||||
614800 37 files
|
||||
|
||||
unix> foxx-manager install ../hello-foxx.zip /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
unix> foxx-manager install ../hello-foxx.zip /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
```
|
||||
|
||||
You can use paths to directories in all functions of the foxx-manager that allow to install foxx applications:
|
||||
You can use paths to directories in all functions of the Foxx-manager that allow to install Foxx applications:
|
||||
|
||||
*install*
|
||||
**install**
|
||||
|
||||
unix> foxx-manager install /Users/arangodb/hello-foxx /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
```
|
||||
unix> foxx-manager install /Users/arangodb/hello-foxx /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
```
|
||||
|
||||
*replace*
|
||||
**replace**
|
||||
|
||||
unix> foxx-manager replace /Users/arangodb/hello-foxx /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
```
|
||||
unix> foxx-manager replace /Users/arangodb/hello-foxx /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
```
|
||||
|
||||
*upgrade*
|
||||
|
||||
unix> foxx-manager upgrade /Users/arangodb/hello-foxx /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
**upgrade**
|
||||
```
|
||||
unix> foxx-manager upgrade /Users/arangodb/hello-foxx /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
```
|
||||
|
|
|
@ -2,40 +2,43 @@
|
|||
|
||||
!SECTION Introduction to Foxx manager
|
||||
|
||||
The Foxx manager is a shell program. It should have been installed under */usr/bin* or */usr/local/bin*
|
||||
when installing the ArangoDB package. An instance of the ArangoDB server must be
|
||||
The Foxx manager is a shell program. It should have been installed under **/usr/bin** or **/usr/local/bin**
|
||||
when installing the ArangoDB package. An instance of the ArangoDB server must be
|
||||
up and running.
|
||||
|
||||
unix> foxx-manager
|
||||
Expecting a command, please try:
|
||||
```
|
||||
unix> foxx-manager
|
||||
Expecting a command, please try:
|
||||
|
||||
Example usage:
|
||||
foxx-manager install <app-info> <mount-point> option1=value1
|
||||
foxx-manager uninstall <mount-point>
|
||||
|
||||
Further help:
|
||||
foxx-manager help for the list of foxx-manager commands
|
||||
foxx-manager --help for the list of options
|
||||
Example usage:
|
||||
foxx-manager install <app-info> <mount-point> option1=value1
|
||||
foxx-manager uninstall <mount-point>
|
||||
|
||||
Further help:
|
||||
foxx-manager help for the list of foxx-manager commands
|
||||
foxx-manager --help for the list of options
|
||||
```
|
||||
The most important commands are
|
||||
|
||||
* *install*: Installs a Foxx application to a local URL and calls its setup method
|
||||
* *uninstall*: Deletes a Foxx application and calls its teardown method
|
||||
* *list*: Lists all installed Foxx applications (alias: *installed*)
|
||||
* **install**: Installs a Foxx application to a local URL and calls its setup method
|
||||
* **uninstall**: Deletes a Foxx application and calls its teardown method
|
||||
* **list**: Lists all installed Foxx applications (alias: **installed**)
|
||||
|
||||
When dealing with a fresh install of ArangoDB, there should be no installed
|
||||
When dealing with a fresh install of ArangoDB, there should be no installed
|
||||
applications besides the system applications that are shipped with ArangoDB.
|
||||
|
||||
unix> foxx-manager list
|
||||
Mount Name Author Description Version Development
|
||||
--------------------- ------------ ------------------ ----------------------------------------------- -------- ------------
|
||||
/_admin/aardvark aardvark ArangoDB GmbH ArangoDB Admin Web Interface 1.0 no
|
||||
/_api/gharial gharial ArangoDB GmbH ArangoDB Graph Module 0.1 no
|
||||
/_system/cerberus cerberus ArangoDB GmbH Password Manager 0.0.1 no
|
||||
/_system/sessions sessions ArangoDB GmbH Session storage for Foxx. 0.1 no
|
||||
/_system/simple-auth simple-auth ArangoDB GmbH Simple password-based authentication for Foxx. 0.1 no
|
||||
--------------------- ------------ ------------------ ----------------------------------------------- -------- ------------
|
||||
5 application(s) found
|
||||
````
|
||||
unix> foxx-manager list
|
||||
Mount Name Author Description Version Development
|
||||
--------------------- ------------ ------------------ ----------------------------------------------- -------- ------------
|
||||
/_admin/aardvark aardvark ArangoDB GmbH ArangoDB Admin Web Interface 1.0 no
|
||||
/_api/gharial gharial ArangoDB GmbH ArangoDB Graph Module 0.1 no
|
||||
/_system/cerberus cerberus ArangoDB GmbH Password Manager 0.0.1 no
|
||||
/_system/sessions sessions ArangoDB GmbH Session storage for Foxx. 0.1 no
|
||||
/_system/simple-auth simple-auth ArangoDB GmbH Simple password-based authentication for Foxx. 0.1 no
|
||||
--------------------- ------------ ------------------ ----------------------------------------------- -------- ------------
|
||||
5 application(s) found
|
||||
```
|
||||
|
||||
There are currently several applications installed, all of them are system applications.
|
||||
You can safely ignore system applications.
|
||||
|
|
|
@ -1,85 +1,95 @@
|
|||
!CHAPTER Install Applications from remote host
|
||||
|
||||
In this chapter we will make use of the foxx manager as described [before](README.md).
|
||||
In this chapter we will make use of the Foxx manager as described [before](README.md).
|
||||
This time we want to install an app hosted on a server.
|
||||
Currently the foxx-manager supports downloads of applications via http and https protocols.
|
||||
Currently the Foxx-manager supports downloads of applications via http and https protocols.
|
||||
|
||||
!SECTION Remote file format
|
||||
The file on the remote server has to be a valid foxx application packed in a zip archive.
|
||||
The zip archive has to contain a top-level directory which is containing the sources of the foxx application.
|
||||
Especially the file *manifest.json* has to be directly contained in this top-level directory.
|
||||
On a unix system you can verify that your zip archive has the correct format if the content looks like this:
|
||||
The file on the remote server has to be a valid Foxx application packed in a zip archive.
|
||||
The zip archive has to contain a top-level directory which is containing the sources of the Foxx application.
|
||||
Especially the file **manifest.json** has to be directly contained in this top-level directory.
|
||||
On an Unix system you can verify that your zip archive has the correct format if the content looks like this:
|
||||
|
||||
unix> unzip -l hello-foxx.zip
|
||||
Archive: hello-foxx.zip
|
||||
0836dc2e81be8264e480a7695b46c1abe7ef153d
|
||||
Length Date Time Name
|
||||
-------- ---- ---- ----
|
||||
0 09-10-14 15:35 hello-foxx/
|
||||
1256 09-10-14 15:35 hello-foxx/README.md
|
||||
11200 09-10-14 15:35 hello-foxx/app.js
|
||||
0 09-10-14 15:35 hello-foxx/assets/
|
||||
0 09-10-14 15:35 hello-foxx/assets/css/
|
||||
82 09-10-14 15:35 hello-foxx/assets/css/base.css
|
||||
86 09-10-14 15:35 hello-foxx/assets/css/custom.css
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/css/
|
||||
22111 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/css/bootstrap-responsive.css
|
||||
16849 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/css/bootstrap-responsive.min.css
|
||||
127247 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/css/bootstrap.css
|
||||
105939 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/css/bootstrap.min.css
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/img/
|
||||
8777 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/img/glyphicons-halflings-white.png
|
||||
12799 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/img/glyphicons-halflings.png
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/jquery/
|
||||
268380 09-10-14 15:35 hello-foxx/assets/vendor/jquery/jquery.js
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/sh/
|
||||
1981 09-10-14 15:35 hello-foxx/assets/vendor/sh/highlighter.css
|
||||
5563 09-10-14 15:35 hello-foxx/assets/vendor/sh/sh_javascript.js
|
||||
5305 09-10-14 15:35 hello-foxx/assets/vendor/sh/sh_main.min.js
|
||||
0 09-10-14 15:35 hello-foxx/files/
|
||||
3266 09-10-14 15:35 hello-foxx/files/index.html
|
||||
398 09-10-14 15:35 hello-foxx/files/static.html
|
||||
361 09-10-14 15:35 hello-foxx/kaffee.coffee
|
||||
0 09-10-14 15:35 hello-foxx/lib/
|
||||
108 09-10-14 15:35 hello-foxx/lib/a.js
|
||||
43 09-10-14 15:35 hello-foxx/lib/c.js
|
||||
1129 09-10-14 15:35 hello-foxx/manifest.json
|
||||
0 09-10-14 15:35 hello-foxx/models/
|
||||
330 09-10-14 15:35 hello-foxx/models/tiger.js
|
||||
0 09-10-14 15:35 hello-foxx/scripts/
|
||||
2065 09-10-14 15:35 hello-foxx/scripts/setup.js
|
||||
1798 09-10-14 15:35 hello-foxx/scripts/teardown.js
|
||||
17727 09-10-14 15:35 hello-foxx/thumbnail.png
|
||||
-------- -------
|
||||
614800 37 files
|
||||
```
|
||||
unix> unzip -l hello-foxx.zip
|
||||
Archive: hello-foxx.zip
|
||||
0836dc2e81be8264e480a7695b46c1abe7ef153d
|
||||
Length Date Time Name
|
||||
-------- ---- ---- ----
|
||||
0 09-10-14 15:35 hello-foxx/
|
||||
1256 09-10-14 15:35 hello-foxx/README.md
|
||||
11200 09-10-14 15:35 hello-foxx/app.js
|
||||
0 09-10-14 15:35 hello-foxx/assets/
|
||||
0 09-10-14 15:35 hello-foxx/assets/css/
|
||||
82 09-10-14 15:35 hello-foxx/assets/css/base.css
|
||||
86 09-10-14 15:35 hello-foxx/assets/css/custom.css
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/css/
|
||||
22111 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/css/bootstrap-responsive.css
|
||||
16849 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/css/bootstrap-responsive.min.css
|
||||
127247 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/css/bootstrap.css
|
||||
105939 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/css/bootstrap.min.css
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/img/
|
||||
8777 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/img/glyphicons-halflings-white.png
|
||||
12799 09-10-14 15:35 hello-foxx/assets/vendor/bootstrap/img/glyphicons-halflings.png
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/jquery/
|
||||
268380 09-10-14 15:35 hello-foxx/assets/vendor/jquery/jquery.js
|
||||
0 09-10-14 15:35 hello-foxx/assets/vendor/sh/
|
||||
1981 09-10-14 15:35 hello-foxx/assets/vendor/sh/highlighter.css
|
||||
5563 09-10-14 15:35 hello-foxx/assets/vendor/sh/sh_javascript.js
|
||||
5305 09-10-14 15:35 hello-foxx/assets/vendor/sh/sh_main.min.js
|
||||
0 09-10-14 15:35 hello-foxx/files/
|
||||
3266 09-10-14 15:35 hello-foxx/files/index.html
|
||||
398 09-10-14 15:35 hello-foxx/files/static.html
|
||||
361 09-10-14 15:35 hello-foxx/kaffee.coffee
|
||||
0 09-10-14 15:35 hello-foxx/lib/
|
||||
108 09-10-14 15:35 hello-foxx/lib/a.js
|
||||
43 09-10-14 15:35 hello-foxx/lib/c.js
|
||||
1129 09-10-14 15:35 hello-foxx/manifest.json
|
||||
0 09-10-14 15:35 hello-foxx/models/
|
||||
330 09-10-14 15:35 hello-foxx/models/tiger.js
|
||||
0 09-10-14 15:35 hello-foxx/scripts/
|
||||
2065 09-10-14 15:35 hello-foxx/scripts/setup.js
|
||||
1798 09-10-14 15:35 hello-foxx/scripts/teardown.js
|
||||
17727 09-10-14 15:35 hello-foxx/thumbnail.png
|
||||
-------- -------
|
||||
614800 37 files
|
||||
```
|
||||
|
||||
Next you have to make this file publicly available over http or https on a webserver.
|
||||
Assume we can download the app at *http://www.example.com/hello.zip*
|
||||
Assume we can download the app at **http://www.example.com/hello.zip**.
|
||||
|
||||
!SECTION Install from remote server
|
||||
|
||||
Having the link to your foxx application at hand you can just hand this link over to the foxx manager:
|
||||
Having the link to your Foxx application at hand you can just hand this link over to the Foxx manager:
|
||||
|
||||
unix> foxx-manager install http://www.example.com/hello.zip /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
```
|
||||
unix> foxx-manager install http://www.example.com/hello.zip /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
```
|
||||
|
||||
ArangoDB will try to download and extract the file stored at the remote location.
|
||||
|
||||
This http or https link can be used in all functions of the foxx-manager that allow to install foxx applications:
|
||||
This http or https link can be used in all functions of the Foxx-manager that allow to install Foxx applications:
|
||||
|
||||
*install*
|
||||
**install**
|
||||
|
||||
unix> foxx-manager install http://www.example.com/hello.zip /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
```
|
||||
unix> foxx-manager install http://www.example.com/hello.zip /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
```
|
||||
|
||||
*replace*
|
||||
**replace**
|
||||
|
||||
unix> foxx-manager replace http://www.example.com/hello.zip /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
```
|
||||
unix> foxx-manager replace http://www.example.com/hello.zip /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
```
|
||||
|
||||
*upgrade*
|
||||
**upgrade**
|
||||
|
||||
unix> foxx-manager upgrade http://www.example.com/hello.zip /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
```
|
||||
unix> foxx-manager upgrade http://www.example.com/hello.zip /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
```
|
||||
|
|
|
@ -1,41 +1,51 @@
|
|||
!CHAPTER Install Applications from github
|
||||
|
||||
In this chapter we will make use of the foxx manager as described [before](README.md).
|
||||
This time we want to install an app out of our version control hosted on github.com TODO:LINK.
|
||||
That means the foxx-manager does not know about the application information and we cannot install it simply by its name.
|
||||
In this chapter we will make use of the Foxx manager as described [before](README.md).
|
||||
This time we want to install an app out of our version control hosted on github.com.
|
||||
That means the Foxx-manager does not know about the application information and we cannot install it simply by its name.
|
||||
|
||||
In order to install an application we need three informations:
|
||||
|
||||
* *Repository*: The name of the repository.
|
||||
* *Username*: The username of the user owning the repository.
|
||||
* *Version*: Branch or Tag name available on the repository.
|
||||
* **Repository**: The name of the repository.
|
||||
* **Username**: The username of the user owning the repository.
|
||||
* **Version**: Branch or Tag name available on the repository.
|
||||
|
||||
As an example, we would like to install [https://www.github.com/arangodb/hello-foxx](https://www.github.com/arangodb/hello-foxx).
|
||||
The *username* is *arangodb*, the *repository* is *hello-foxx*.
|
||||
If we do not define a *version* it will automatically install the master branch.
|
||||
The **username** is **arangodb**, the **repository** is **hello-foxx**.
|
||||
If we do not define a **version** it will automatically install the master branch.
|
||||
|
||||
unix> foxx-manager install git:arangodb/hello-foxx /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
```
|
||||
unix> foxx-manager install git:arangodb/hello-foxx /example
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /example
|
||||
```
|
||||
|
||||
The hello-foxx app has defined a tag for version 1.4.4 that is named "v1.4.4".
|
||||
We can simply append this tag in the install command:
|
||||
|
||||
unix> foxx-manager install git:arangodb/hello-foxx:v1.4.4 /legacy
|
||||
Application hello-foxx version 1.4.4 installed successfully at mount point /legacy
|
||||
```
|
||||
unix> foxx-manager install git:arangodb/hello-foxx:v1.4.4 /legacy
|
||||
Application hello-foxx version 1.4.4 installed successfully at mount point /legacy
|
||||
```
|
||||
|
||||
This reference for github repositories can be used in all functions of the foxx-manager that allow to install foxx applications:
|
||||
This reference for github repositories can be used in all functions of the Foxx-manager that allow to install Foxx applications:
|
||||
|
||||
* *install*
|
||||
* **install**
|
||||
|
||||
unix> foxx-manager install git:arangodb/hello-foxx:v1.4.4 /legacy
|
||||
Application hello-foxx version 1.4.4 installed successfully at mount point /legacy
|
||||
```
|
||||
unix> foxx-manager install git:arangodb/hello-foxx:v1.4.4 /legacy
|
||||
Application hello-foxx version 1.4.4 installed successfully at mount point /legacy
|
||||
```
|
||||
|
||||
* *replace*
|
||||
* **replace**
|
||||
|
||||
unix> foxx-manager replace git:arangodb/hello-foxx:v1.4.4 /legacy
|
||||
Application hello-foxx version 1.4.4 installed successfully at mount point /legacy
|
||||
```
|
||||
unix> foxx-manager replace git:arangodb/hello-foxx:v1.4.4 /legacy
|
||||
Application hello-foxx version 1.4.4 installed successfully at mount point /legacy
|
||||
```
|
||||
|
||||
* *upgrade*
|
||||
* **upgrade**
|
||||
|
||||
unix> foxx-manager upgrade git:arangodb/hello-foxx:v1.5.0 /legacy
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /legacy
|
||||
```
|
||||
unix> foxx-manager upgrade git:arangodb/hello-foxx:v1.5.0 /legacy
|
||||
Application hello-foxx version 1.5.0 installed successfully at mount point /legacy
|
||||
```
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
!SECTION Quick navigation
|
||||
* [Quick start](#quick-start)
|
||||
* [Create a new Application](#new-application)
|
||||
* [Interactive Documentation](#Interactive Documentation)
|
||||
* [Interactive Documentation](#interactive-doc)
|
||||
* [Developing in Foxx](#developing)
|
||||
* [Foxx folder structure](#folder-structure)
|
||||
* [List content of a collection](#list-elements)
|
||||
|
@ -202,7 +202,7 @@ Now lets also allow to store an optional `name` by changing the following lines:
|
|||
```
|
||||
|
||||
To test it you can for example store the following object.
|
||||
Note the _key is the internal identifier for this
|
||||
Note the \_key is the internal identifier for this
|
||||
object and can either be user-defined or will be generated otherwise.
|
||||
In this tutorial we will refer to this key again.
|
||||
|
||||
|
@ -253,7 +253,7 @@ controller.get('/firstCollection/:id', function (req, res) {
|
|||
|
||||
This route now allows us to read exactly one specific document stored in our collection.
|
||||
In the last route we have inserted the "Alice" document, now we want to get that one back.
|
||||
In order to achieve this we have to replace the "_id" with the "_key" we have stored earlier.
|
||||
In order to achieve this we have to replace the "\_id" with the "\_key" we have stored earlier.
|
||||
In the interactive documentation there is a text field to enter the value, or you can execute the following CURL command:
|
||||
|
||||
```
|
||||
|
@ -470,7 +470,7 @@ Some details you should know about the code:
|
|||
!SUBSECTION Conclusion
|
||||
|
||||
Now we have managed to create a very basic CRUD based Foxx.
|
||||
It is a REST-based wrapper arpund the interface of one of ArangoDBs collections and you can now start to include custom functionality into it.
|
||||
It is a REST-based wrapper around the interface of one of ArangoDBs collections and you can now start to include custom functionality into it.
|
||||
The first custom function we have created already is the byName query.
|
||||
It has stored an AQL on the server-side keeping your application clean of it.
|
||||
Now you can also access this query from several applications increasing the reusability of code.
|
||||
Now you can also access this query from several applications increasing the re-usability of code.
|
||||
|
|
|
@ -1,28 +1,30 @@
|
|||
!CHAPTER Available Debugging mechanisms
|
||||
|
||||
We are talking about the production mode for foxx.
|
||||
We are talking about the production mode for Foxx.
|
||||
We assume that the development process is over and you have a (third-party) client using your API.
|
||||
In this case you will most likely want to expose stacktraces or detailed error information to the requesting client.
|
||||
This of course restricts the debugging mechanisms for the client and requires to consult the logs.
|
||||
Nevertheless the client should see if there is an internal error occurring therefore all foxxes will have the behavior described in the following.
|
||||
Nevertheless the client should see if there is an internal error occurring therefore all Foxxes will have the behavior described in the following.
|
||||
|
||||
Right now we assume you have the production mode enabled (default after install)
|
||||
|
||||
unix>foxx-manager production /example
|
||||
Activated production mode for Application hello-foxx version 1.5.0 on mount point /example
|
||||
```
|
||||
unix>foxx-manager production /example
|
||||
Activated production mode for Application hello-foxx version 1.5.0 on mount point /example
|
||||
```
|
||||
|
||||
!SECTION Errors during install
|
||||
|
||||
Malformed foxx applications cannot be installed via the foxx-manager.
|
||||
Malformed Foxx applications cannot be installed via the Foxx-manager.
|
||||
You will get detailed error information if you try to.
|
||||
However you might create the following situation:
|
||||
|
||||
1. Set a foxx to development mode.
|
||||
2. Make it malformed.
|
||||
3. Set it to production mode.
|
||||
1. Set a Foxx to development mode
|
||||
2. Make it malformed
|
||||
3. Set it to production mode
|
||||
|
||||
In this case all routes of this foxx will create a general, html page for thirdparty clients stating that there was an internal error.
|
||||
This page does not contain any information specific for your foxx.
|
||||
In this case all routes of this Foxx will create a general, HTML page for third party clients stating that there was an internal error.
|
||||
This page does not contain any information specific for your Foxx.
|
||||
|
||||
TODO SCREEEEEEENNNN
|
||||
|
||||
|
@ -31,34 +33,36 @@ This page does not contain any information specific for your foxx.
|
|||
If you have an unhandled error in one of your routes the error message will be returned together with an HTTP status code 500.
|
||||
It will not contain the stacktrace of your error.
|
||||
|
||||
unix>curl -X GET http://localhost:8529/_db/_system/example/failed
|
||||
HTTP/1.1 500 Internal Error
|
||||
Server: ArangoDB
|
||||
Connection: Keep-Alive
|
||||
Content-Type: application/json
|
||||
Content-Length: 27
|
||||
```
|
||||
unix>curl -X GET http://localhost:8529/_db/_system/example/failed
|
||||
HTTP/1.1 500 Internal Error
|
||||
Server: ArangoDB
|
||||
Connection: Keep-Alive
|
||||
Content-Type: application/json
|
||||
Content-Length: 27
|
||||
|
||||
{"error":"Unhandled Error"}
|
||||
{"error":"Unhandled Error"}
|
||||
```
|
||||
|
||||
!SECTION Errors in logs
|
||||
|
||||
Independent of the errors presented in the routes on requests foxxes will always log errors to the log-file if catched by the default error handlers.
|
||||
Independent from the errors presented in the routes on requests Foxxes will always log errors to the log-file if caught by the default error handlers.
|
||||
The log entries will always contain stacktraces and error messages:
|
||||
|
||||
ERROR Error in foxx route '{ "match" : "/failed", "methods" : [ "get" ] }': 'Unhandled Error', Stacktrace: Error: Unhandled Error
|
||||
ERROR at fail (js/apps/_db/_system/example/APP/app.js:279:13)
|
||||
ERROR at js/apps/_db/_system/example/APP/app.js:284:5
|
||||
ERROR at Object.res.action.callback (./js/server/modules/org/arangodb/foxx/internals.js:108:5)
|
||||
ERROR at ./js/server/modules/org/arangodb/foxx/routing.js:346:19
|
||||
ERROR at execute (./js/server/modules/org/arangodb/actions.js:1291:7)
|
||||
ERROR at next (./js/server/modules/org/arangodb/actions.js:1308:7)
|
||||
ERROR at [object Object]:386:5
|
||||
ERROR at execute (./js/server/modules/org/arangodb/actions.js:1291:7)
|
||||
ERROR at routeRequest (./js/server/modules/org/arangodb/actions.js:1312:3)
|
||||
ERROR at foxxRouting (./js/server/modules/org/arangodb/actions.js:1082:7)
|
||||
ERROR at execute (./js/server/modules/org/arangodb/actions.js:1291:7)
|
||||
ERROR at Object.routeRequest (./js/server/modules/org/arangodb/actions.js:1312:3)
|
||||
ERROR at Function.actions.defineHttp.callback (js/actions/api-system.js:51:15)
|
||||
ERROR
|
||||
|
||||
|
||||
```
|
||||
ERROR Error in foxx route '{ "match" : "/failed", "methods" : [ "get" ] }': 'Unhandled Error', Stacktrace: Error: Unhandled Error
|
||||
ERROR at fail (js/apps/_db/_system/example/APP/app.js:279:13)
|
||||
ERROR at js/apps/_db/_system/example/APP/app.js:284:5
|
||||
ERROR at Object.res.action.callback (./js/server/modules/org/arangodb/foxx/internals.js:108:5)
|
||||
ERROR at ./js/server/modules/org/arangodb/foxx/routing.js:346:19
|
||||
ERROR at execute (./js/server/modules/org/arangodb/actions.js:1291:7)
|
||||
ERROR at next (./js/server/modules/org/arangodb/actions.js:1308:7)
|
||||
ERROR at [object Object]:386:5
|
||||
ERROR at execute (./js/server/modules/org/arangodb/actions.js:1291:7)
|
||||
ERROR at routeRequest (./js/server/modules/org/arangodb/actions.js:1312:3)
|
||||
ERROR at foxxRouting (./js/server/modules/org/arangodb/actions.js:1082:7)
|
||||
ERROR at execute (./js/server/modules/org/arangodb/actions.js:1291:7)
|
||||
ERROR at Object.routeRequest (./js/server/modules/org/arangodb/actions.js:1312:3)
|
||||
ERROR at Function.actions.defineHttp.callback (js/actions/api-system.js:51:15)
|
||||
ERROR
|
||||
```
|
||||
|
|
|
@ -7,34 +7,32 @@ This is the default mode for all newly installed apps and should always be used
|
|||
|
||||
Activating the production mode is done with a single command:
|
||||
|
||||
unix> foxx-manager production /example
|
||||
Activated production mode for Application hello-foxx version 1.5.0 on mount point /example
|
||||
```
|
||||
unix> foxx-manager production /example
|
||||
Activated production mode for Application hello-foxx version 1.5.0 on mount point /example
|
||||
```
|
||||
|
||||
Now the app will not be listed in *listDevelopment*:
|
||||
|
||||
unix> foxx-manager listDevelopment
|
||||
Mount Name Author Description Version Development
|
||||
--------- ----------- ------------- ----------------------------------------- -------- ------------
|
||||
--------- ----------- ------------- ----------------------------------------- -------- ------------
|
||||
0 application(s) found
|
||||
Now the app will not be listed in **listDevelopment**:
|
||||
|
||||
```
|
||||
unix> foxx-manager listDevelopment
|
||||
Mount Name Author Description Version Development
|
||||
--------- ----------- ------------- ----------------------------------------- -------- ------------
|
||||
--------- ----------- ------------- ----------------------------------------- -------- ------------
|
||||
0 application(s) found
|
||||
```
|
||||
!SECTION Effects
|
||||
|
||||
For a Foxx application in production mode the following effects apply:
|
||||
<dl>
|
||||
<dt>Application Caching</dt>
|
||||
<dl>
|
||||
The first time an application is requested it's routing is computed and cached.
|
||||
It is guaranteed that subsequent requests to this application will get the cached routing.
|
||||
That implies that changing the sources of an app will not have any effect.
|
||||
It also guarantees that requests will be answered at the highest possible speed.
|
||||
The cache might be flushed whenever ArangoDB is restarted or an application in development mode is requested.
|
||||
</dl>
|
||||
<dt>Only internal Debugging information</dt>
|
||||
<dl>
|
||||
Whenever the application is requested and an unhandled error occurs only a generic error message will be returned.
|
||||
Stack traces are never delivered via the public API.
|
||||
For more information see the [Debugging](Debugging.md) section.
|
||||
</dl>
|
||||
</dl>
|
||||
|
||||
**Application Caching**
|
||||
The first time an application is requested it's routing is computed and cached.
|
||||
It is guaranteed that subsequent requests to this application will get the cached routing.
|
||||
That implies that changing the sources of an app will not have any effect.
|
||||
It also guarantees that requests will be answered at the highest possible speed.
|
||||
The cache might be flushed whenever ArangoDB is restarted or an application in development mode is requested.
|
||||
|
||||
**Only internal Debugging information**
|
||||
Whenever the application is requested and an unhandled error occurs only a generic error message will be returned.
|
||||
Stack traces are never delivered via the public API.
|
||||
For more information see the [Debugging](Debugging.md) section.
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
!CHAPTER Running foxx in production
|
||||
!CHAPTER Running Foxx in production
|
||||
|
||||
This chapter will explain to you how to run a foxx in a production environment.
|
||||
Be it a microservice, an API with a user interface or an internal library.
|
||||
This chapter will explain to you how to run Foxx in a production environment.
|
||||
Be it a microservice, an API with an user interface or an internal library.
|
||||
|
||||
Before reading this chapter you should make sure to at least read one of the install sections beforehand to get a good staring point.
|
||||
|
||||
At first we will introduce the production mode and describe it's side effects.
|
||||
At first we will introduce the production mode and describe its side effects.
|
||||
This is the default mode for all freshly installed Foxxes.
|
||||
It will compute the routing of a foxx only once and afterwards use the cached version.
|
||||
It will compute the routing of a Foxx only once and afterwards use the cached version.
|
||||
This mode is not suitable for development, it has less error output and does not react to source file changes.
|
||||
|
||||
[Read More](Productionmode.md)
|
||||
|
||||
Next you will learn about the restricted debugging mechanisms.
|
||||
The focus of this mode is to seal your source files and never send any stacktraces unintentionally.
|
||||
However there might still be unknown bugs in your foxx, these will still be logged into the server-side log.
|
||||
However there might still be unknown bugs in your Foxx, these will still be logged into the server-side log.
|
||||
|
||||
[Read More](Debugging.md)
|
||||
|
||||
If you want to update to a new version of your application the next chapter is important for you:
|
||||
|
||||
[New Versions](Foxx/Production/Upgrade.md)
|
||||
[New Versions](Upgrade.md)
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
!CHAPTER Upgrade to a new version
|
||||
|
||||
In this chapter we want to cover the case where you have a foxx in production and want to upgrade it to a new version.
|
||||
In this chapter we want to cover the case where you have a Foxx in production and want to upgrade it to a new version.
|
||||
In this specific case you do not want to execute the setup and teardown scripts.
|
||||
A simple uninstall / install procedure would first trigger both scripts and would trigger a very short downtime of your app.
|
||||
Therefore the foxx-manager offers an update procedure, which acts similar to install, but overwrites the existing foxx.
|
||||
Therefore the Foxx-manager offers an update procedure, which acts similar to install, but overwrites the existing Foxx.
|
||||
In addition it does neither trigger setup nor teardown.
|
||||
|
||||
unix> foxx-manager update itzpapalotl:1.0.0 /example
|
||||
Application itzpapalotl version 1.0.0 installed successfully at mount point /example
|
||||
```
|
||||
unix> foxx-manager update itzpapalotl:1.0.0 /example
|
||||
Application itzpapalotl version 1.0.0 installed successfully at mount point /example
|
||||
```
|
||||
|
||||
Also you will not experience any downtime of your foxx.
|
||||
Also you will not experience any downtime of your Foxx.
|
||||
One thread will be responsible to update to the newer version, all other threads will continue to serve the old version.
|
||||
As soon as the update thread is finished rerouting of all other threads is scheduled as well and eventually they will converge to the newest version of the app:
|
||||
All requests issued before the rerouting scheduling will be answered with the old version, all requests issued after will be answered with the new version.
|
||||
|
|
|
@ -6,7 +6,7 @@ With the framework you can embed complex queries and data-focused business logic
|
|||
|
||||
Using Foxx will give you benefits above writing the code in a separate applications.
|
||||
First of all it yields performance benefits, the data analysis and modification is executed as close to the data as possible.
|
||||
Also it requires one network hop less as the foxx has direct access to the data and does not have to query a database located on a different server.
|
||||
Also it requires one network hop less as the Foxx has direct access to the data and does not have to query a database located on a different server.
|
||||
Second your application is completely free of any database related information like queries, it is just requesting a endpoint that gives the data in the expected format.
|
||||
This also allows to reuse this endpoint in different applications without copying the queries.
|
||||
Third Foxx adds another level of security to your application, you can manage the access rights on any level you like: application, collection, document or even attribute.
|
||||
|
@ -194,3 +194,5 @@ This chapter will present the more advanced capabilities of Foxx.
|
|||
It requires that you know the details presented in the chapters before.
|
||||
Here you will learn about Foxx feature exports and imports to implement abstract APIs for reuse in several Apps.
|
||||
Furthermore you will learn about background and periodical tasks in Foxx applications.
|
||||
|
||||
[Read More](Advanced/README.md)
|
||||
|
|
|
@ -89,8 +89,8 @@ case "$1" in
|
|||
|
||||
c=0
|
||||
|
||||
while test -f $PIDFILE -a $c -lt 30; do
|
||||
log_progress_msg "$NAME"
|
||||
while test -f $PIDFILE -a $c -lt 30 && ps --pid `cat $PIDFILE` > /dev/null; do
|
||||
log_progress_msg "."
|
||||
sleep 2
|
||||
c=`expr $c + 1`
|
||||
done
|
||||
|
|
|
@ -89,8 +89,8 @@ case "$1" in
|
|||
|
||||
c=0
|
||||
|
||||
while test -f $PIDFILE -a $c -lt 30; do
|
||||
log_progress_msg "$NAME"
|
||||
while test -f $PIDFILE -a $c -lt 30 && ps --pid `cat $PIDFILE` > /dev/null; do
|
||||
log_progress_msg "."
|
||||
sleep 2
|
||||
c=`expr $c + 1`
|
||||
done
|
||||
|
|
|
@ -110,7 +110,7 @@ namespace triagens {
|
|||
return _statistics = FUNC::acquire();
|
||||
|
||||
#else
|
||||
return 0;
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,7 @@ namespace triagens {
|
|||
|
||||
if (_statistics != nullptr) {
|
||||
FUNC::release(_statistics);
|
||||
_statistics = 0;
|
||||
_statistics = nullptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -137,7 +137,7 @@ namespace triagens {
|
|||
#ifdef TRI_ENABLE_FIGURES
|
||||
|
||||
agent->replace(_statistics);
|
||||
_statistics = 0;
|
||||
_statistics = nullptr;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
@ -150,13 +150,13 @@ namespace triagens {
|
|||
#ifdef TRI_ENABLE_FIGURES
|
||||
|
||||
STAT* statistics = _statistics;
|
||||
_statistics = 0;
|
||||
_statistics = nullptr;
|
||||
|
||||
return statistics;
|
||||
|
||||
#else
|
||||
|
||||
return 0;
|
||||
return nullptr;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "statistics.h"
|
||||
|
||||
#include "Basics/locks.h"
|
||||
#include "Basics/Mutex.h"
|
||||
#include "Basics/MutexLocker.h"
|
||||
|
||||
#ifndef BSD
|
||||
#ifdef __FreeBSD__
|
||||
|
@ -45,20 +45,6 @@
|
|||
using namespace triagens::basics;
|
||||
using namespace std;
|
||||
|
||||
#ifdef TRI_USE_SPIN_LOCK_STATISTICS
|
||||
#define STATISTICS_TYPE TRI_spin_t
|
||||
#define STATISTICS_INIT TRI_InitSpin
|
||||
#define STATISTICS_DESTROY TRI_DestroySpin
|
||||
#define STATISTICS_LOCK TRI_LockSpin
|
||||
#define STATISTICS_UNLOCK TRI_UnlockSpin
|
||||
#else
|
||||
#define STATISTICS_TYPE TRI_mutex_t
|
||||
#define STATISTICS_INIT TRI_InitMutex
|
||||
#define STATISTICS_DESTROY TRI_DestroyMutex
|
||||
#define STATISTICS_LOCK TRI_LockMutex
|
||||
#define STATISTICS_UNLOCK TRI_UnlockMutex
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private request statistics variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -67,7 +53,7 @@ using namespace std;
|
|||
/// @brief lock for lists
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static STATISTICS_TYPE RequestListLock;
|
||||
static triagens::basics::Mutex RequestListLock;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief free list
|
||||
|
@ -86,15 +72,15 @@ static TRI_statistics_list_t RequestFreeList;
|
|||
TRI_request_statistics_t* TRI_AcquireRequestStatistics () {
|
||||
TRI_request_statistics_t* statistics = nullptr;
|
||||
|
||||
STATISTICS_LOCK(&RequestListLock);
|
||||
{
|
||||
MUTEX_LOCKER(RequestListLock);
|
||||
|
||||
if (RequestFreeList._first != nullptr) {
|
||||
statistics = (TRI_request_statistics_t*) RequestFreeList._first;
|
||||
RequestFreeList._first = RequestFreeList._first->_next;
|
||||
if (RequestFreeList._first != nullptr) {
|
||||
statistics = (TRI_request_statistics_t*) RequestFreeList._first;
|
||||
RequestFreeList._first = RequestFreeList._first->_next;
|
||||
}
|
||||
}
|
||||
|
||||
STATISTICS_UNLOCK(&RequestListLock);
|
||||
|
||||
return statistics;
|
||||
}
|
||||
|
||||
|
@ -103,10 +89,9 @@ TRI_request_statistics_t* TRI_AcquireRequestStatistics () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_ReleaseRequestStatistics (TRI_request_statistics_t* statistics) {
|
||||
STATISTICS_LOCK(&RequestListLock);
|
||||
MUTEX_LOCKER(RequestListLock);
|
||||
|
||||
if (statistics == nullptr) {
|
||||
STATISTICS_UNLOCK(&RequestListLock);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -158,9 +143,7 @@ void TRI_ReleaseRequestStatistics (TRI_request_statistics_t* statistics) {
|
|||
RequestFreeList._last = (TRI_statistics_entry_t*) statistics;
|
||||
}
|
||||
|
||||
RequestFreeList._last->_next = 0;
|
||||
|
||||
STATISTICS_UNLOCK(&RequestListLock);
|
||||
RequestFreeList._last->_next = nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -173,7 +156,7 @@ void TRI_FillRequestStatistics (StatisticsDistribution& totalTime,
|
|||
StatisticsDistribution& ioTime,
|
||||
StatisticsDistribution& bytesSent,
|
||||
StatisticsDistribution& bytesReceived) {
|
||||
STATISTICS_LOCK(&RequestListLock);
|
||||
MUTEX_LOCKER(RequestListLock);
|
||||
|
||||
totalTime = *TRI_TotalTimeDistributionStatistics;
|
||||
requestTime = *TRI_RequestTimeDistributionStatistics;
|
||||
|
@ -181,8 +164,6 @@ void TRI_FillRequestStatistics (StatisticsDistribution& totalTime,
|
|||
ioTime = *TRI_IoTimeDistributionStatistics;
|
||||
bytesSent = *TRI_BytesSentDistributionStatistics;
|
||||
bytesReceived = *TRI_BytesReceivedDistributionStatistics;
|
||||
|
||||
STATISTICS_UNLOCK(&RequestListLock);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -193,7 +174,7 @@ void TRI_FillRequestStatistics (StatisticsDistribution& totalTime,
|
|||
/// @brief lock for lists
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static STATISTICS_TYPE ConnectionListLock;
|
||||
static triagens::basics::Mutex ConnectionListLock;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief free list
|
||||
|
@ -210,17 +191,17 @@ static TRI_statistics_list_t ConnectionFreeList;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_connection_statistics_t* TRI_AcquireConnectionStatistics () {
|
||||
TRI_connection_statistics_t* statistics = 0;
|
||||
TRI_connection_statistics_t* statistics = nullptr;
|
||||
|
||||
STATISTICS_LOCK(&ConnectionListLock);
|
||||
{
|
||||
MUTEX_LOCKER(ConnectionListLock);
|
||||
|
||||
if (ConnectionFreeList._first != nullptr) {
|
||||
statistics = (TRI_connection_statistics_t*) ConnectionFreeList._first;
|
||||
ConnectionFreeList._first = ConnectionFreeList._first->_next;
|
||||
if (ConnectionFreeList._first != nullptr) {
|
||||
statistics = (TRI_connection_statistics_t*) ConnectionFreeList._first;
|
||||
ConnectionFreeList._first = ConnectionFreeList._first->_next;
|
||||
}
|
||||
}
|
||||
|
||||
STATISTICS_UNLOCK(&ConnectionListLock);
|
||||
|
||||
return statistics;
|
||||
}
|
||||
|
||||
|
@ -229,16 +210,15 @@ TRI_connection_statistics_t* TRI_AcquireConnectionStatistics () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_ReleaseConnectionStatistics (TRI_connection_statistics_t* statistics) {
|
||||
STATISTICS_LOCK(&ConnectionListLock);
|
||||
MUTEX_LOCKER(ConnectionListLock);
|
||||
|
||||
if (statistics == nullptr) {
|
||||
STATISTICS_UNLOCK(&ConnectionListLock);
|
||||
return;
|
||||
}
|
||||
|
||||
if (statistics->_http) {
|
||||
if (statistics->_connStart != 0) {
|
||||
if (statistics->_connEnd == 0) {
|
||||
if (statistics->_connStart != 0.0) {
|
||||
if (statistics->_connEnd == 0.0) {
|
||||
TRI_HttpConnectionsStatistics.incCounter();
|
||||
}
|
||||
else {
|
||||
|
@ -263,8 +243,6 @@ void TRI_ReleaseConnectionStatistics (TRI_connection_statistics_t* statistics) {
|
|||
}
|
||||
|
||||
ConnectionFreeList._last->_next = nullptr;
|
||||
|
||||
STATISTICS_UNLOCK(&ConnectionListLock);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -276,15 +254,13 @@ void TRI_FillConnectionStatistics (StatisticsCounter& httpConnections,
|
|||
vector<StatisticsCounter>& methodRequests,
|
||||
StatisticsCounter& asyncRequests,
|
||||
StatisticsDistribution& connectionTime) {
|
||||
STATISTICS_LOCK(&ConnectionListLock);
|
||||
MUTEX_LOCKER(ConnectionListLock);
|
||||
|
||||
httpConnections = TRI_HttpConnectionsStatistics;
|
||||
totalRequests = TRI_TotalRequestsStatistics;
|
||||
methodRequests = TRI_MethodRequestsStatistics;
|
||||
asyncRequests = TRI_AsyncRequestsStatistics;
|
||||
connectionTime = *TRI_ConnectionTimeDistributionStatistics;
|
||||
|
||||
STATISTICS_UNLOCK(&ConnectionListLock);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -313,16 +289,13 @@ TRI_server_statistics_t TRI_GetServerStatistics () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void FillStatisticsList (TRI_statistics_list_t* list, size_t element, size_t count) {
|
||||
size_t i;
|
||||
TRI_statistics_entry_t* entry;
|
||||
|
||||
entry = (TRI_statistics_entry_t*) TRI_Allocate(TRI_CORE_MEM_ZONE, element, true);
|
||||
auto entry = static_cast<TRI_statistics_entry_t*>(TRI_Allocate(TRI_CORE_MEM_ZONE, element, true));
|
||||
|
||||
list->_first = entry;
|
||||
list->_last = entry;
|
||||
|
||||
for (i = 1; i < count; ++i) {
|
||||
entry = (TRI_statistics_entry_t*) TRI_Allocate(TRI_CORE_MEM_ZONE, element, true);
|
||||
for (size_t i = 1; i < count; ++i) {
|
||||
entry = static_cast<TRI_statistics_entry_t*>(TRI_Allocate(TRI_CORE_MEM_ZONE, element, true));
|
||||
|
||||
list->_last->_next = entry;
|
||||
list->_last = entry;
|
||||
|
@ -335,6 +308,7 @@ static void FillStatisticsList (TRI_statistics_list_t* list, size_t element, siz
|
|||
|
||||
static void DestroyStatisticsList (TRI_statistics_list_t* list) {
|
||||
TRI_statistics_entry_t* entry = list->_first;
|
||||
|
||||
while (entry != nullptr) {
|
||||
TRI_statistics_entry_t* next = entry->_next;
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, entry);
|
||||
|
@ -598,8 +572,6 @@ void TRI_InitialiseStatistics () {
|
|||
|
||||
FillStatisticsList(&RequestFreeList, sizeof(TRI_request_statistics_t), QUEUE_SIZE);
|
||||
|
||||
STATISTICS_INIT(&RequestListLock);
|
||||
|
||||
// .............................................................................
|
||||
// generate the connection statistics queue
|
||||
// .............................................................................
|
||||
|
@ -607,8 +579,6 @@ void TRI_InitialiseStatistics () {
|
|||
ConnectionFreeList._first = ConnectionFreeList._last = nullptr;
|
||||
|
||||
FillStatisticsList(&ConnectionFreeList, sizeof(TRI_connection_statistics_t), QUEUE_SIZE);
|
||||
|
||||
STATISTICS_INIT(&ConnectionListLock);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue