zetapush / zetapush-next-open-specification

Open specification for Next ZetaPush version
0 stars 0 forks source link

Utilisation du broadcast #47

Closed ghoullier closed 2 years ago

ghoullier commented 6 years ago

Existant

Les macroscript ZetaPush V2 permette à un developpeur de broadcaster le résultats d'une macro sur une ressource donnée. Une ressource est une chaine de caractère permettant d'identifié un utilisateur ou une groupe d'utilisateur.

macroscript hello() {
} broadcast('userKey') {
    key: 'value'
}

Dans le cadre de celtia, le developpeur de cloud function doit avoir la même possibilité.

Proposition 1

Normalisation de la structure de données retournée par les méthodes

module.exports = class {
    method1(parameters, response) {
        // Retourne le résultat à l'utilisateur ayant l'userKey passé en paramètre
        return response.broadcast({
            key: 'value'
        }, 'userKey');
    }
    method2(parameters, response) {
        // Retourne le résultat à l'utilisateur appelant
        return response.notify({
            key: 'value'
        });
    }
}

Avantages:

Inconvénients:

Proposition 2

Le broadcast est utilisé comme une API de messaging et non un type de retour

module.exports = class {
    method1(parameters, response) {
        // Envoie un message à l'utilisateur ayant l'userKey passé en paramètre
        response.broadcast({
            key: 'value'
        }, 'userKey');
        response.broadcast({
            key2: 'value2'
        }, 'userKey2');
        // L'utilisateur ayant appelé la cloud function lui reçoit le retour de la cloud function
    }
    method2(parameters, response) {
        // Retourne le résultat à l'utilisateur appelant
        return {
            key: 'value'
        }
    }
}

Avantages:

Inconvénients:

damienld22 commented 6 years ago

Cette première proposition me plait bien mais je ne comprend ce qu'est réellement le paramètre response ?

L'appelant de la Cloud Function est obligé de le passer en paramètre ?

ghoullier commented 6 years ago

Non c'est injecté par le code du SDK. Ce qui est envoyé par l'application client c'est le premier paramètre parameters.

damienld22 commented 6 years ago

D'accord je comprend mieux.

Je trouve finalement que la seconde proposition est plus pertinente puisque le comportement d'un broadcast doit selon moi se rapprocher d'un système de messaging.

La possibilité de faire plusieurs broadcast est très intéressante je trouve ! Ensuite selon moi, le fait que l'on casse la logique des macros v2 n'est pas un réel problème.

ghoullier commented 6 years ago

Oui, je suis assez d'accord. Du coup si on part sur la seconde proposition on peut meme envisager de renommer le broadcast en un autre terme si besoin.

damienld22 commented 6 years ago

Le mot clé broadcast est bien je trouve après je pensais à transmit ?

ghoullier commented 6 years ago

Oui notify aussi.

damienld22 commented 6 years ago

Oui je préfère notify du coup

raphael22 commented 6 years ago

Je trouve broadcast plus parlant.

aurelien-baudet commented 6 years ago

Et bah je vais encore proposer autre chose :

Cas simples et récurrents :

module.exports = class {
        // le résultat est envoyé à tous les destinataires grâce à sendTo
        @sendTo(['user1',        // envoie à un utilisateur identifié par son id applicatif
                 () => {...}],   // provider qui génère une liste ou un user à partir des paramètres et du retour de la fonction
                 includeSender=true) 
    method0(monParam1Amoi, monParam2Amoi) {
                // je fais mon pitit calcul
                result = ...
                // je retourne le résultat
        return result
    }
module.exports = class {
        constructor(messagingService) {}

    method0(monParam1Amoi, monParam2Amoi) {
                // je fais mon pitit calcul
                result = ...
                // je retourne le résultat
        this.messagingService.sendTo(result, 'user1', ...)
    }

Cas avancés :

module.exports = class {
        constructor(messagingService) {}

    method1(monParam1Amoi, monParam2Amoi) {
                // je fais mon pitit calcul
                result1 = ...
                // je retourne le résultat
        this.messagingService.sendTo(result1, 'user1', ...)

                // je fais mon pitit calcul
                result2 = ...
                // je retourne le résultat
        this.messagingService.sendTo(result2, 'user1', ...)
    }

    method2(monParam1Amoi, monParam2Amoi) {
        // Retourne le résultat à l'utilisateur appelant
        return {
            key: 'value'
        }
    }
}

Le but est de se concentrer sur le code utile et d'extraire au maximum les problématiques techniques du code. Donc on laisse l'utilisateur coder une fonction avec ses propres paramètres et son propre retour et zetapush lui permet d'ajouter des comportements sans lui demander de casser son code (ou le moins possible). Ceci toujours dans l'optique de pouvoir faire du test unitaire sur le comportement de la fonction et non pas tester zetapush

ghoullier commented 6 years ago

Je suis pas super fan de l'annotation pour le broadcast, car ça oblige a mettre la userKey en dur en dehors de la cloud function. Je suis plutot partisant d'une API, ça permet de fonctionner simplement en JS et TS. L'utilisation du service de messaging est une bonne approche pour l'implémenter rapidement par contre!!

ghoullier commented 6 years ago

@damienld22 Voila comment on peut l'implémenter avec l'API actuelle.

Server

const { Messaging } = require('@zetapush/platform');

module.exports = class Api {
  static get injected() {
    return [Messaging];
  }
  constructor(messaging) {
    this.messaging = messaging;
  }
  addMessageToConversation(parameters) {
    this.messaging.send({
      channel: 'onAddMessageToConversation',
      target: '',
      data: parameters.message
    });
    return parameters.message;
  }
}

Client

class Api extends ZetaPushPlatform.Queue {
    addMessageToConversation(parameters) {
        return this.$publish('addMessageToConversation', '', parameters);
    }
}

const api = client.createAsyncTaskService({
  Type: Api,
});

const events = client.createService({
    Type: ZetaPushPlatform.Messaging,
    listener: {
        onAddMessageToConversation(response) {
            console.log('onAddMessageToConversation', response);
        }
    }
});
aurelien-baudet commented 6 years ago

@ghoullier Juste pour préciser, dans mon optique, on propose les deux, le messaging et la possibilité d'utiliser les annotations. Le choix est fait par le développeur.

@all L'autre point que je souhaite préciser c'est de ne pas utiliser un terme technique (qui peut être mal compris) alors qu'on en a finalement pas réellement besoin. Du point de vue du dev, envoyer à 1 ou N, c'est le même objectif : envoyer. Le comment (broadcast ou non) c'est notre tambouille interne mais nos utilisateurs n'ont pas forcément besoin qu'on leur remonte cette complexité.