Blog

How to Backup Your Data Tables in Backendless

by on June 25, 2019

Backup Data Tables

In this article, we will show you how to write a service that will backup your application data with a time interval you specify. To do this, we will be using Cloud Code, a JavaScript timer, and the console SDK.

The result of this operation will be an archive with the data of all your tables (or, if you wish, you can modify the service for backing up specific individual tables, geo-points, application settings, etc.).

First, we need to create a simple timer which in the future will call a service for backup.

Open your application in Backendless Console and go to the Business Logic menu on the left. Open the Timers menu and click New Timer. A modal window will appear, as in the screenshot below. You can give any name you wish to the timer, excluding spaces and wild cards. We will call it BackupDataTables. Also in this window, you can set the schedule for calling the timer. We set the value to daily, and repeat every one day.

Add New Timer

Now you should see your timer in the list:

Timer Business Logic

Next, go to the Coding tab and load your project:

Load Project from Coding Tab

Open the downloaded project in your preferred code editor. Don’t forget to run npm install to install all the dependencies.

To write the service, we need the Console API. The Console API was originally meant to be internal and not used in any automation. That’s why it was never added to the Client SDKs. This wasn’t a technical decision, but rather a measure to increase the stability of the application. The operations available only with Console API are mostly those changing the database structure or some internal configurations. In our case, we will use the API to export the tables.

Using your most convenient package manager (yarn, npm), install the module `backendless-console-sdk`.

Now let’s create a file in the services folder. Just call it backup.js, meaning that other backup methods for other data may potentially appear in the service.

The contents of this file will be as follows (see notes in the comments in the code):

 

'use strict'

const consoleSDK = require('backendless-console-sdk')

// our service starts here
class Backup {

 /**
  * @route POST /tables
  * @returns {Promise.<void>}
  */
 async backupTables() {
   const { login, password } = this.config // values provided in console configuring this service after deploy
   const { appId } = this.request.context // more about invocation context here https://backendless.com/docs/bl-js/bl_invocation_context.html


   // create api client using `createClient` method of console SDK
   // it expects server url, which we can take from Backendless SDK’s ‘serverURL’
   const apiClient = consoleSDK.createClient(Backendless.serverURL)


   // because of using of console API requires to be authorized in order to do requests
   // we login console’s developer. You may create special developer for this purposes
   // or use your own credentials
   await apiClient.user.login(login, password)


   // here we retrieve exported data from console
   // it will return an object of type:
   // { geofences: [...], categories: [...], tables: [{ id, name, related: [...]}, ...] }
   const exportedData = await apiClient.transfer.getExportedData(appId)
   // map table ids to send it for starting import of these tables
   const tableIds = exportedData.tables.map(table => table.id)

   const exportPayload = {
     addDataTypes       : true,
     appsettings        : false, // set true in order to export app settings
     schemaOnly         : false, // set true in order to export tables schems only
     addDataGeoRelations: false,
     geofences          : [], // list of geofences ids
     categories         : [], // list of geo categories ids
     tables             : tableIds // list of tables ids
   }


   // start import
   return apiClient.transfer.startExport(appId, exportPayload)
 }
}



// add service and as a second argument you may pass an array of configuration items
// here we pass login and password fields
Backendless.ServerCode.addService(Backup, [{
 name       : 'login',
 type       : 'string',
 displayName: 'Login',
 required   : true,
 order      : 0
}, {
 name       : 'password',
 type       : 'string',
 displayName: 'Password',
 required   : true,
 order      : 1
}])

Also, make sure you have “Dynamic schema definition” enabled, otherwise you might encounter an error during deployment. It’s needed to create a new Data Table BlConfigurationItemDescription dynamically. The table stores all the configurations for your API Services. Once it’s done, you can disable “Dynamic schema definition”.

Disable Dynamic Schema Definition

In the timers folder, find your timer and make the following changes:

 

'use strict'

/**
* Export data tables and store in Files storage.
* Executes according to the schedule
* Once per day.
*/
Backendless.ServerCode.addTimer({

 name: 'BackupDataTables',

 startDate: Date.now(),

 frequency: {
   schedule: 'daily',

   repeat: { every: 1 }
 },

 execute() {
   return Backendless.CustomServices.invoke('Backup', 'backupTables')
 }
})

Run ‘npm run deploy’ and, once deployed, go to the Console’s Business Logic menu, click on your service and then click Configure Service (gear icon):

Configure Deployed Service

The configuration modal will open:

Service Configuration

Enter Login and Password and click Save.

That’s it. If you want to check, go to the Timers tab, find your timer in the list of timers and invoke it:

Invoke Timer In Backendless

After that you can go to the Files section, open the ‘export’ folder and find your export archive. You can then download your archive and, if necessary, import into your app in the Manage > Import section.

While we hope you never need to restore your data from backups, it’s important to have a backup in place in case the worst were to happen. As they say – better safe than sorry. Happy coding!

Leave a Reply