github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/sdk/javascript/messaging/stream.js (about)

     1  /**
     2   * Copyright 2016 Intel Corporation
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   * ------------------------------------------------------------------------------
    16   */
    17  
    18  'use strict'
    19  
    20  const crypto = require('crypto')
    21  const uuid = require('uuid/v4')
    22  const zmq = require('zeromq')
    23  
    24  const assert = require('assert')
    25  
    26  const { Message } = require('../protobuf')
    27  const Deferred = require('./deferred')
    28  const { ValidatorConnectionError } = require('../processor/exceptions')
    29  
    30  const _encodeMessage = (messageType, correlationId, content) => {
    31    assert(
    32      typeof messageType === 'number',
    33      `messageType must be a number; was ${messageType}`
    34    )
    35    assert(
    36      typeof correlationId === 'string',
    37      `correlationId must be a string; was ${correlationId}`
    38    )
    39    assert(
    40      content !== undefined || content !== null,
    41      'content must not be null or undefined'
    42    )
    43    assert(
    44      Buffer.isBuffer(content),
    45      `content must be a buffer; was ${
    46        content.constructor ? content.constructor.name : typeof content
    47      }`
    48    )
    49  
    50    return Message.encode({
    51      messageType,
    52      correlationId,
    53      content
    54    }).finish()
    55  }
    56  
    57  const _generateId = () =>
    58    crypto.createHash('sha256')
    59      .update(uuid())
    60      .digest('hex')
    61  
    62  class Stream {
    63    constructor (url) {
    64      this._url = url
    65  
    66      this._initial_connection = true
    67    }
    68  
    69    connect (onConnectCb) {
    70      if (this._onConnectCb) {
    71        console.log(`Attempting to reconnect to ${this._url}`)
    72      }
    73  
    74      this._onConnectCb = onConnectCb
    75  
    76      this._futures = {}
    77      this._socket = zmq.socket('dealer')
    78      this._socket.setsockopt('identity', Buffer.from(uuid(), 'utf8'))
    79      this._socket.on('connect', () => {
    80        console.log(`Connected to ${this._url}`)
    81        onConnectCb()
    82      })
    83      this._socket.on('disconnect', (fd, endpoint) => this._handleDisconnect())
    84      this._socket.monitor(250, 0)
    85      this._socket.connect(this._url)
    86  
    87      this._initial_connection = false
    88    }
    89  
    90    close () {
    91      this._socket.setsockopt(zmq.ZMQ_LINGER, 0)
    92      this._socket.unmonitor()
    93      this._socket.close()
    94      this._socket = null
    95    }
    96  
    97    _handleDisconnect () {
    98      console.log(`Disconnected from ${this._url}`)
    99      this.close()
   100      Object.keys(this._futures).forEach((correlationId) => {
   101        this._futures[correlationId].reject(
   102          new ValidatorConnectionError('The connection to the validator was lost')
   103        )
   104      })
   105  
   106      this.connect(this._onConnectCb)
   107    }
   108  
   109    send (type, content) {
   110      if (this._socket) {
   111        const correlationId = _generateId()
   112        let deferred = new Deferred()
   113        this._futures[correlationId] = deferred
   114  
   115        try {
   116          this._socket.send(_encodeMessage(type, correlationId, content))
   117        } catch (e) {
   118          delete this._futures[correlationId]
   119          return Promise.reject(e)
   120        }
   121  
   122        return deferred.promise
   123          .then(result => {
   124            delete this._futures[correlationId]
   125            return result
   126          })
   127          .catch(err => {
   128            delete this._futures[correlationId]
   129            throw err
   130          })
   131      } else {
   132        let err = null
   133        if (this._initial_connection) {
   134          err = new Error('Must call `connect` before calling `send`')
   135        } else {
   136          err = new ValidatorConnectionError(
   137            'The connection to the validator was lost'
   138          )
   139        }
   140  
   141        return Promise.reject(err)
   142      }
   143    }
   144  
   145    sendBack (type, correlationId, content) {
   146      if (this._socket) {
   147        this._socket.send(_encodeMessage(type, correlationId, content))
   148      }
   149    }
   150  
   151    onReceive (cb) {
   152      this._socket.on('message', buffer => {
   153        let message = Message.decode(buffer)
   154        if (this._futures[message.correlationId]) {
   155          this._futures[message.correlationId].resolve(message.content)
   156        } else {
   157          process.nextTick(() => cb(message))
   158        }
   159      })
   160    }
   161  }
   162  
   163  module.exports = { Stream }