github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-supply-chain-master/ledger_sync/db/state.js (about) 1 /** 2 * Copyright 2018 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 'use strict' 18 19 const _ = require('lodash') 20 const r = require('rethinkdb') 21 const db = require('./') 22 23 24 const valueNames = { 25 BYTES: 'bytesValue', 26 BOOLEAN: 'booleanValue', 27 NUMBER: 'numberValue', 28 STRING: 'stringValue', 29 ENUM: 'enumValue', 30 LOCATION: 'locationValue' 31 } 32 33 const xformStruct = properties => { 34 return _.fromPairs(properties.map(property => { 35 const value = property.dataType === 'STRUCT' 36 ? xformStruct(property.structValues) 37 : property[ valueNames[property.dataType] ] 38 return [property.name, value] 39 })) 40 } 41 42 const addBlockState = (tableName, indexName, indexValue, doc, blockNum) => { 43 return db.modifyTable(tableName, table => { 44 return table 45 .getAll(indexValue, { index: indexName }) 46 .filter({ endBlockNum: Number.MAX_SAFE_INTEGER }) 47 .coerceTo('array') 48 .do(oldDocs => { 49 return oldDocs 50 .filter({ startBlockNum: blockNum }) 51 .coerceTo('array') 52 .do(duplicates => { 53 return r.branch( 54 // If there are duplicates, do nothing 55 duplicates.count().gt(0), 56 duplicates, 57 58 // Otherwise, update the end block on any old docs, 59 // and insert the new one 60 table 61 .getAll(indexValue, { index: indexName }) 62 .update({ endBlockNum: blockNum }) 63 .do(() => { 64 return table.insert(_.assign({}, doc, { 65 startBlockNum: blockNum, 66 endBlockNum: Number.MAX_SAFE_INTEGER 67 })) 68 }) 69 ) 70 }) 71 }) 72 }) 73 } 74 75 const addAgent = (agent, blockNum) => { 76 return addBlockState('agents', 'publicKey', agent.publicKey, 77 agent, blockNum) 78 } 79 80 const addRecord = (record, blockNum) => { 81 return addBlockState('records', 'recordId', record.recordId, 82 record, blockNum) 83 } 84 85 const addRecordType = (type, blockNum) => { 86 return addBlockState('recordTypes', 'name', type.name, 87 type, blockNum) 88 } 89 90 const addProperty = (property, blockNum) => { 91 return addBlockState('properties', 'attributes', 92 ['name', 'recordId'].map(k => property[k]), 93 property, blockNum) 94 } 95 96 const addPropertyPage = (page, blockNum) => { 97 return db.queryTable('properties', properties => { 98 return properties 99 .getAll([page.name, page.recordId], { index: 'attributes' }) 100 .filter({ endBlockNum: Number.MAX_SAFE_INTEGER }) 101 }) 102 .then(properties => { 103 if (properties.length === 0) { 104 const attrs = `${page.name}, ${page.recordId}` 105 return console.warn("WARNING! Unable to find page's Property:", attrs) 106 } 107 108 const property = properties[0] 109 110 // Convert enum indexes into names, or empty strings if not an enum 111 if (property.dataType === 'ENUM') { 112 page.reportedValues.forEach(reported => { 113 reported.enumValue = property.enumOptions[reported.enumValue] 114 }) 115 } else { 116 page.reportedValues.forEach(reported => { 117 reported.enumValue = '' 118 }) 119 } 120 121 // Convert `structValues` array into `structValue` object 122 if (property.dataType === 'STRUCT') { 123 page.reportedValues.forEach(reported => { 124 reported.structValue = xformStruct(reported.structValues) 125 delete reported.structValues 126 }) 127 } else { 128 page.reportedValues.forEach(reported => { 129 reported.structValue = {} 130 delete reported.structValues 131 }) 132 } 133 134 }) 135 .then(() => { 136 return addBlockState('propertyPages', 'attributes', 137 ['name', 'recordId', 'pageNum'].map(k => page[k]), 138 page, blockNum) 139 }) 140 } 141 142 const addProposal = (proposal, blockNum) => { 143 return addBlockState( 144 'proposals', 'attributes', 145 ['recordId', 'timestamp', 'receivingAgent', 'role'].map(k => proposal[k]), 146 proposal, blockNum) 147 } 148 149 module.exports = { 150 addAgent, 151 addRecord, 152 addRecordType, 153 addProperty, 154 addPropertyPage, 155 addProposal 156 }