github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/sdk/javascript/processor/index.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 {
    21    TpRegisterRequest,
    22    TpRegisterResponse,
    23    TpUnregisterRequest,
    24    TpProcessRequest,
    25    TpProcessResponse,
    26    PingResponse,
    27    Message
    28  } = require('../protobuf')
    29  
    30  const {
    31    InternalError,
    32    AuthorizationException,
    33    InvalidTransaction,
    34    ValidatorConnectionError
    35  } = require('./exceptions')
    36  
    37  const Context = require('./context')
    38  
    39  const { Stream } = require('../messaging/stream')
    40  
    41  /**
    42   * TransactionProcessor is a generic class for communicating with a
    43   * validator and routing transaction processing requests to a
    44   * registered handler. It uses ZMQ and channels to handle requests
    45   * concurrently.
    46   *
    47   * @param {string} url - the URL of the validator
    48   */
    49  class TransactionProcessor {
    50    constructor (url) {
    51      this._stream = new Stream(url)
    52      this._handlers = []
    53    }
    54  
    55    /**
    56     * addHandler adds the given handler to the transaction processor so
    57     * it can receive transaction processing requests. All handlers must
    58     * be added prior to starting the processor.
    59     *
    60     * @param {TransactionHandler} handler - a handler to be added
    61     */
    62    addHandler (handler) {
    63      this._handlers.push(handler)
    64    }
    65  
    66    /**
    67     * start connects the transaction processor to a validator and
    68     * starts listening for requests and routing them to an appropriate
    69     * handler.
    70     */
    71    start () {
    72      this._stream.connect(() => {
    73        this._stream.onReceive(message => {
    74          if (message.messageType !== Message.MessageType.TP_PROCESS_REQUEST) {
    75            if (message.messageType === Message.MessageType.PING_REQUEST) {
    76              console.log(`Received Ping`)
    77              let pingResponse = PingResponse.create()
    78              this._stream.sendBack(
    79                Message.MessageType.PING_RESPONSE,
    80                message.correlationId,
    81                PingResponse.encode(pingResponse).finish()
    82              )
    83              return
    84            }
    85            console.log(
    86              `Ignoring ${Message.MessageType.stringValue(message.messageType)}`
    87            )
    88            return
    89          }
    90  
    91          const request = TpProcessRequest.toObject(
    92            TpProcessRequest.decode(message.content),
    93            { defaults: false }
    94          )
    95          const context = new Context(this._stream, request.contextId)
    96  
    97          if (this._handlers.length > 0) {
    98            let txnHeader = request.header
    99  
   100            let handler = this._handlers.find(
   101              (candidate) =>
   102                candidate.transactionFamilyName === txnHeader.familyName &&
   103                candidate.versions.includes(txnHeader.familyVersion))
   104  
   105            if (handler) {
   106              let applyPromise
   107              try {
   108                applyPromise = Promise.resolve(handler.apply(request, context))
   109              } catch(err) {
   110                applyPromise = Promise.reject(err)
   111              }
   112              applyPromise
   113              .then(() =>
   114                TpProcessResponse.create({
   115                  status: TpProcessResponse.Status.OK
   116                })
   117              )
   118              .catch(e => {
   119                if (e instanceof InvalidTransaction) {
   120                  console.log(e)
   121                  return TpProcessResponse.create({
   122                    status: TpProcessResponse.Status.INVALID_TRANSACTION,
   123                    message: e.message,
   124                    extendedData: e.extendedData
   125                  })
   126                } else if (e instanceof InternalError) {
   127                  console.log('Internal Error Occurred', e)
   128                  return TpProcessResponse.create({
   129                    status: TpProcessResponse.Status.INTERNAL_ERROR,
   130                    message: e.message,
   131                    extendedData: e.extendedData
   132                  })
   133                } else if (e instanceof ValidatorConnectionError) {
   134                  console.log('Validator disconnected.  Ignoring.')
   135                } else if (e instanceof AuthorizationException) {
   136                  console.log(e)
   137                  return TpProcessResponse.create({
   138                    status: TpProcessResponse.Status.INVALID_TRANSACTION,
   139                    message: e.message,
   140                    extendedData: e.extendedData
   141                  })
   142                } else {
   143                  console.log('Unhandled exception, returning INTERNAL_ERROR', e)
   144                  return TpProcessResponse.create({
   145                    status: TpProcessResponse.Status.INTERNAL_ERROR,
   146                    message: `Unhandled exception in ${txnHeader.familyName} ${txnHeader.familyVersion}`
   147                  })
   148                }
   149              })
   150              .then((response) => {
   151                if (response) {
   152                  this._stream.sendBack(
   153                    Message.MessageType.TP_PROCESS_RESPONSE,
   154                    message.correlationId,
   155                    TpProcessResponse.encode(response).finish()
   156                  )
   157                }
   158              })
   159              .catch(e => console.log('Unhandled error on sendBack', e))
   160            }
   161          }
   162        })
   163  
   164        this._handlers.forEach(handler => {
   165          handler.versions.forEach(version => {
   166            this._stream.send(
   167              Message.MessageType.TP_REGISTER_REQUEST,
   168              TpRegisterRequest.encode({
   169                family: handler.transactionFamilyName,
   170                version: version,
   171                namespaces: handler.namespaces
   172              }).finish())
   173              .then(content => TpRegisterResponse.decode(content))
   174              .then(ack => {
   175                let { transactionFamilyName: familyName } = handler
   176                let status =
   177                  ack.status === TpRegisterResponse.Status.OK
   178                    ? 'succeeded'
   179                    : 'failed'
   180                console.log(
   181                  `Registration of [${familyName} ${version}] ${status}`
   182                )
   183              })
   184              .catch(e => {
   185                let { transactionFamilyName: familyName } = handler
   186                console.log(
   187                  `Registration of [${familyName} ${version}] Failed!`,
   188                  e
   189                )
   190              })
   191          })
   192        })
   193      })
   194  
   195      process.on('SIGINT', () => this._handleShutdown())
   196      process.on('SIGTERM', () => this._handleShutdown())
   197    }
   198  
   199    _handleShutdown () {
   200      console.log('Unregistering transaction processor')
   201      this._stream.send(
   202        Message.MessageType.TP_UNREGISTER_REQUEST,
   203        TpUnregisterRequest.encode().finish()
   204      )
   205      process.exit()
   206    }
   207  }
   208  
   209  module.exports = {
   210    TransactionProcessor
   211  }