@@ -16,6 +16,8 @@ import Data.Vector as Vector
1616 , (!)
1717 )
1818import qualified Data.ByteString.Lazy as LBS
19+ import Data.IORef (readIORef , newIORef , modifyIORef )
20+ import Control.Monad.Except (ExceptT (.. ), runExceptT )
1921
2022import qualified Peer.ChaincodeShim as Pb
2123
@@ -111,27 +113,71 @@ instance ChaincodeStubInterface DefaultChaincodeStub where
111113 -- -- getStateValiationParameter :: ccs -> String -> Either Error [ByteString]
112114 -- getStateValiationParameter ccs key = Left notImplemented
113115 --
116+
117+ -- TODO: Implement better error handling/checks etc
114118 -- getStateByRange :: ccs -> Text -> Text -> IO (Either Error StateQueryIterator)
115119 getStateByRange ccs startKey endKey =
116120 let payload = getStateByRangePayload startKey endKey
117121 message = buildChaincodeMessage GET_STATE_BY_RANGE payload (txId ccs) (channelId ccs)
118- bsToSqi :: ByteString -> Either Error StateQueryIterator
122+ -- We have listenForResponse a :: IO (Either Error ByteString)
123+ -- and the function bsToSqi :: ByteString -> IO (Either Error StateQueryIterator)
124+ -- And want IO (Either Error StateQueryIterator)
125+ -- ExceptT is a monad transformer that allows us to compose these by binding over IO Either
126+ bsToSqi :: ByteString -> ExceptT Error IO StateQueryIterator
119127 bsToSqi bs = let eeaQueryResponse = parse (decodeMessage (FieldNumber 1 )) bs :: Either ParseError Pb. QueryResponse in
120128 case eeaQueryResponse of
121- Left _ -> Left ParseError
122- Right queryResponse -> Right StateQueryIterator {
123- sqiChannelId = getChannelId ccs
124- , sqiTxId = getTxId ccs
125- , sqiResponse = queryResponse
126- , sqiCurrentLoc = 0
127- }
129+ Left _ -> ExceptT $ pure $ Left ParseError
130+ Right queryResponse -> ExceptT $ do
131+ -- queryResponse and currentLoc are IORefs as they need to be mutated
132+ -- as a part of the next() function
133+ queryResponseIORef <- newIORef queryResponse
134+ currentLocIORef <- newIORef 0
135+ pure $ Right StateQueryIterator {
136+ sqiChannelId = getChannelId ccs
137+ , sqiTxId = getTxId ccs
138+ , sqiResponse = queryResponseIORef
139+ , sqiCurrentLoc = currentLocIORef
140+ }
128141 in do
129142 e <- (sendStream ccs) message
130143 case e of
131144 Left err -> error (" Error while streaming: " ++ show err)
132145 Right _ -> pure ()
133- (bsToSqi =<< ) <$> listenForResponse (recvStream ccs)
146+ runExceptT $ ExceptT (listenForResponse (recvStream ccs)) >>= bsToSqi
147+
148+ -- TODO : implement all these interface functions
149+ instance StateQueryIteratorInterface StateQueryIterator where
150+ -- hasNext :: sqi -> Bool
151+ hasNext sqi = True
152+ -- close :: sqi -> IO (Maybe Error)
153+ close _ = pure Nothing
154+ -- next :: sqi -> IO (Either Error Pb.KV)
155+ next _ = pure $ Left $ Error " not implemented"
134156
157+ nextResult :: StateQueryIterator -> IO (Either Error Pb. QueryResultBytes )
158+ nextResult sqi = do
159+ currentLoc <- readIORef $ sqiCurrentLoc sqi
160+ queryResponse <- readIORef $ sqiResponse sqi
161+ -- Checking if there are more local results
162+ if (currentLoc < Prelude. length (Pb. queryResponseResults $ queryResponse)) then
163+ let queryResult = pure $ Right $ (Pb. queryResponseResults $ queryResponse) ! currentLoc in
164+ do
165+ modifyIORef (sqiCurrentLoc sqi) (+ 1 )
166+ if ((currentLoc + 1 ) == Prelude. length (Pb. queryResponseResults $ queryResponse)) then
167+ do
168+ fetchNextQueryResult sqi
169+ queryResult
170+ else
171+ queryResult
172+ else pure $ Left $ Error " Invalid iterator state"
173+
174+ -- TODO : this function is only called when the local result list has been
175+ -- iterated through and there are more results to get from the peer
176+ -- It makes a call to get the next QueryResponse back from the peer
177+ -- and mutates the response with the new QueryResponse and set currentLoc back to 0
178+ fetchNextQueryResult :: StateQueryIterator -> IO (Either Error StateQueryIterator )
179+ fetchNextQueryResult sqi = pure $ Left $ Error " not yet implemented"
180+
135181 --
136182 -- -- getStateByRangeWithPagination :: ccs -> String -> String -> Int32 -> String -> Either Error (StateQueryIterator, Pb.QueryResponseMetadata)
137183 -- getStateByRangeWithPagination ccs startKey endKey pageSize bookmark = Left notImplemented
@@ -203,28 +249,4 @@ instance ChaincodeStubInterface DefaultChaincodeStub where
203249 -- getTxTimestamp ccs = Right txTimestamp
204250 --
205251 -- -- setEvent :: ccs -> String -> ByteArray -> Maybe Error
206- -- setEvent ccs = Right notImplemented
207-
208- instance StateQueryIteratorInterface StateQueryIterator where
209- -- hasNext :: sqi -> Bool
210- hasNext sqi = True
211- -- close :: sqi -> Maybe Error
212- close _ = Nothing
213- -- next :: sqi -> Either Error Pb.KV
214- next _ = Left $ Error " not implemented"
215-
216- nextResult :: StateQueryIterator -> IO (Either Error Pb. QueryResultBytes )
217- nextResult sqi = let x = _one =<< (fetchNextQueryResult sqi) in _two
218- -- if (sqiCurrentLoc sqi) < Prelude.length (Pb.queryResponseResults $ sqiResponse sqi) then
219- -- pure $ Right $ (Pb.queryResponseResults $ sqiResponse sqi) ! (sqiCurrentLoc sqi)
220- -- else pure $ Left $ Error "what"
221- -- if Pb.queryResponseHasMore $ sqiResponse sqi then
222- -- x
223- -- -- (nextResult =<<) =<< (fetchNextQueryResult sqi)
224- -- -- _ <$> (fetchNextQueryResult sqi)
225- -- else pure $ Left $ Error "Error retrieving next queryResult"
226-
227-
228- -- x = fetchNextQueryResult sqi >>= (\eeSqi -> pure $ eeSqi >>= (\a -> pure $ nextResult a))
229- fetchNextQueryResult :: StateQueryIterator -> IO (Either Error StateQueryIterator )
230- fetchNextQueryResult sqi = pure $ Left $ Error " not yet implemented"
252+ -- setEvent ccs = Right notImplemented
0 commit comments