File d'attente Firebase

Comment utiliser la file d’attente Firebase comme backend pour votre application

Firebase fournit le backend en tant que service, en tant que développeur d’applications, vous n’avez pas la possibilité d’avoir du code backend.

Cet exemple montre comment utiliser la file d’attente Firebase pour créer un backend qui fonctionnera au-dessus de la base de données Firebase et servira de backend pour votre application frontale.

Avant d’entrer dans le code, comprenons l’architecture, comment cela va fonctionner. Par souci de brièveté, supposons que nous utilisons le site Web comme serveur frontend et NodeJs comme backend

Conditions préalables

  1. Créez une application Firebase à l’aide de votre compte Google

  2. Ajoutez Firebase à votre page Web. Utilisez bower install firebase --save

  3. Créez un compte de service en utilisant votre nouveau compte firebase créé (Paramètres-> Autorisations -> Comptes de service -> CRÉER UN COMPTE DE SERVICE -> (spécifiez le nom et cochez cette case “Fournir une nouvelle clé privée”) -> enregistrez le fichier json, nous en aura besoin plus tard.

  4. Configurez le serveur NodeJs qui peut être hébergé dans votre environnement préféré

  5. Créez le point de terminaison suivant dans queue/specs

    “request_response”:

     {
         "error_state": "request_error_processing",
         "finished_state": "finished_state",
         "in_progress_state": "request_in_progress",
         "start_state": "request_started"
     }
    
  6. À l’intérieur du serveur NodeJs, installez la version côté serveur de Firebase, “npm install firebase –save”, et initialisez votre compte de service à l’aide du fichier json que nous avons obtenu à l’étape 3, il ressemble à ceci

    firebase.initializeApp({ serviceAccount: ‘./your_file.json’, databaseURL: ‘get_from_firebase_account’ });

Architecture

Voici tout le cycle comment cela fonctionne.

Du côté frontal, vous allez suivre ces étapes

  1. En utilisant Firebase Web SDK, vous écrivez vos demandes directement dans la base de données Firebase dans la file d’attente/tâches du point de terminaison, appelons cela votre demande que vous envoyez au backend.
  2. après avoir inséré votre tâche, vous enregistrez l’écouteur sur le point de terminaison queue/tasks/{taskKey} qui sera appelé lorsque le backend aura fini de traiter votre demande, en écrivant la réponse dans la tâche ci-dessus

Dans le backend, vous allez faire ces étapes

  1. Créer un serveur qui écoute à l’infini les “files d’attente/tâches” du point de terminaison
  2. Traite vos tâches et réécrit les données de réponse dans file d'attente/tâches/réponse
  3. Supprimer la tâche

Tout d’abord, créez cette fonction d’assistance, qui fournit un moyen de gérer les rappels et les promesses ensemble

function createPromiseCallback() {
    var cb;
    var promise = new Promise(function (resolve, reject) {
        cb = function (err, data) {
            if (err) return reject(err);
            return resolve(data);
        };
    });
    cb.promise = promise;
    return cb;
}

Dans le côté frontal, vous aurez cette fonction

function sendRequest(kind, params, cb) {

    cb = cb || createPromiseCallback();
    var requestObject = {
        kind: kind,
        params: params
    };
    var tasksRef = firebase.database().ref('queue/tasks');

    var requestKey = tasksRef.push().key;

    var requestRef = tasksRef.child(requestKey);

    function requestHandshake(snap) {
        if (snap && snap.exists() && (snap.val().response || snap.val()._state ===    config.firebase.task.finishState || snap.val()._error_details)) {
            var snapVal = snap.val();
            if (snapVal._error_details) {
                cb(snapVal._error_details.error);
            } else {
            cb(null, snapVal.response);
        }
        requestRef.off('value', requestHandshake);
    }
   }

   var bulkUpdate = {};
   bulkUpdate['queue/tasks/' + requestKey + '/request'] = requestObject;
   bulkUpdate['queue/tasks/' + requestKey + '/_state'] = config.firebase.task.startState;

   firebase.database().ref().update(bulkUpdate)
    .then(function (snap) {
        requestRef.on('value', requestHandshake);
    }).catch(function (err) {
        cb(err);
    });

   return cb.promise;
  }

vous pouvez utiliser cette fonction comme sendRequest('CreateHouseFacade', {houseName:'Test'}).

Le paramètre Kind est pour le backend, pour savoir quelle méthode appeler pour traiter la demande. Params sert à transmettre des informations supplémentaires sur les paramètres.

Et voici le code backend

const database = firebase.database();
const queueRef = database.ref('queue');

const queueOptions = {
    'specId': 'request_response',
    'sanitize': false,
    'suppressStack': false,
    'numWorkers': 3
};

function removeTask(task) {
    var taskRef = queueRef.child(`tasks/${task._id}`);
    return taskRef.remove();
}

function processTask(data, progress, resolve, reject) {
    try {
        requestHandler(data.request).then(response => {
            data.response = response || null;
            return resolve(data);
        }).catch(err => {
            return reject(err);
        }).then(snap => {
            removeTask(data);
        });
    } catch (err) {
        reject(err).then(snap => removeTask(data));
    }
}

function requestHandler(request) {
    if (!request || !request.kind) throw new Error('Absent Request or Kind');
    var deferredResponse = requestHandlerFactory(request.kind, request.params);
    return deferredResponse;
}

function requestHandlerFactory(kind, params) {
    // It includes mapping all your backend services
    switch (kind) {
        case 'CreateHouseFacade': return myService(params)
        default: throw new Error(`Invalid kind ${kind} was specified`);
    }
}

La fonction myService contient votre code de logique métier qui va accomplir la requête CreateHouseFacade.