bitemyapp/bloodhound

No response type available for bulk operation result?

robinp opened this issue · 4 comments

Hello,

While there's an EsError type, it doesn't seem suited to parse the error returned by a bulk op, for example:

{"took":0, "errors":true, "items":[
 {"index":{"_index":"...","_type":"_doc","_id":"...","status":429,"error":{"type":"cluster_block_exception","reason":"index [xxx] blocked by: [TOO_MANY_REQUESTS/12/disk usage exceeded flood-stage watermark, index has read-only-allow-delete block];"}}}]

(Note that this is a trimmed-down bulk request of 1 items, to simplify).

Pinging #144 on somewhat related.

FYI sketch of something:

data BulkResponse = BulkResponse                           
    { bulkTook        :: Int
    , bulkErrors      :: Bool
    , bulkActionItems :: [BulkActionItem]
    }                                                                                                                                                                                                                                                                                                                        
    deriving (Show, Generic)

data BulkActionItem = BulkActionItem
    { baiAction :: BulkAction
    , baiItem   :: BulkItem                                                                                                                                   
    }  
    deriving (Show, Generic)
                                                                               
data BulkItem = BulkItem
    { biIndex  :: Text
    , biId     :: Text
    , biStatus :: Maybe Int
    , biError  :: Maybe BulkError
    }
    deriving (Show, Generic)

data BulkAction = Index | Create | Delete | Update
    deriving (Show, Generic)

data BulkError = BulkError
    { beType   :: Text
    , beReason :: Text
    }
    deriving (Show, Generic)

instance FromJSON BulkResponse where
    parseJSON = withObject "BulkResponse" $ \o ->
        BulkResponse <$> o .: "took" <*> o .: "errors" <*> o .: "items"

instance FromJSON BulkActionItem where
    parseJSON j =
        parseItem Index j
            <|> parseItem Create j
            <|> parseItem Delete j
            <|> parseItem Update j
      where
            -- | The object has a single key: value pair, where the key encodes 
            -- the action.
        parseItem :: BulkAction -> A.Value -> A.Parser BulkActionItem
        parseItem action = withObject "BulkActionItem" $ \o -> do
            v <- o .: toS actionText
            pure $! BulkActionItem { baiAction = action, baiItem = v }
          where
            actionText :: Text
            actionText = case action of
                Index  -> "index"
                Create -> "create"
                Delete -> "delete"
                Update -> "update"

instance FromJSON BulkItem where
    parseJSON = withObject "BulkItem" $ \o ->
        BulkItem
            <$> o
            .:  "_index"
            <*> o
            .:  "_id"
            <*> o
            .:? "status" -- allegedly present but ES example shows a case where it is missing.. so..
            <*> o
            .:? "error"

instance FromJSON BulkError where
    parseJSON = withObject "BulkError"
        $ \o -> BulkError <$> o .: "type" <*> o .: "reason"

testErrorBody :: Text
testErrorBody = [text|
            {"took":0,"errors":true,"items":[{"index":{"_index":"theidx","_type":"_doc","_id":"some:id:1","status":429,"error":{"type":"cluster_block_exception","reason":"index [theidx] blocked by: [TOO_MANY_REQUESTS/12/disk usage exceeded flood-stage watermark, index has read-only-allow-delete block];"}}}]}
        |]

testSuccessBody :: Text
testSuccessBody = [text|
     {"took":7, "errors": false, "items":[{"index":{"_index":"test","_id":"1","_version":1,"result":"created","forced_refresh":false}}]}
     |]

Feel free to use.

Thanks for your report and your contribution, I'll have a look tomorrow.

I have pushed it! Thanks a lot!

Thank you! Just a not for posterity, one still needs to use the parseEsResponse helper, since on full-batch level errors, ES still returns that kind of error.