bloodhound 0.23.0.0 → 0.23.0.1
raw patch · 8 files changed
+101/−23 lines, 8 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- README.md +20/−11
- bloodhound.cabal +9/−2
- changelog.md +11/−0
- src/Database/Bloodhound/Internal/Client/BHRequest.hs +21/−6
- src/Database/Bloodhound/Internal/Versions/Common/Types/Newtypes.hs +4/−4
- tests/Test/DocumentsSpec.hs +15/−0
- tests/Test/JSONSpec.hs +14/−0
- tests/TestsUtils/Common.hs +7/−0
README.md view
@@ -1,4 +1,9 @@-Bloodhound [](https://travis-ci.org/bitemyapp/bloodhound) [](https://hackage.haskell.org/package/bloodhound)+Bloodhound +++++[](https://hackage.haskell.org/package/bloodhound) ========== @@ -21,10 +26,13 @@ Version compatibility --------------------- -See our [TravisCI](https://travis-ci.org/bitemyapp/bloodhound) for a-listing of Elasticsearch version we test against.+See the [Github compatibility workflow](./.github/workflows/compat.yml) for a+listing of Elasticsearch and OpenSearch versions we test against. +The workflow executions can be seen in the [Github actions+view](https://github.com/bitemyapp/bloodhound/actions/workflows/compat.yml). + Stability --------- @@ -33,15 +41,16 @@ Testing ------- -The TravisCI tests are run using [Stack](http://docs.haskellstack.org/en/stable/README.html). You should use Stack instead of `cabal` to build and test Bloodhound to avoid compatibility problems. You will also need to have an Elasticsearch instance running at `localhost:9200` in order to execute some of the tests. See the "Version compatibility" section above for a list of Elasticsearch versions that are officially validated against in TravisCI.+The Bloodhound project uses Github workflows using Cabal to test for regressions+and compatibility. A convenient development environment is provided by Nix and a+Makefile, though the project can be built with only Cabal. -Steps to run the tests locally:- 1. Dig through the [past releases] (https://www.elastic.co/downloads/past-releases) section of the Elasticsearch download page and install the desired Elasticsearch versions.- 2. Install [Stack] (http://docs.haskellstack.org/en/stable/README.html#how-to-install)- 3. In your local Bloodhound directory, run `stack setup && stack build`- 4. Start the desired version of Elasticsearch at `localhost:9200`, which should be the default.- 5. Run `stack test` in your local Bloodhound directory.- 6. The unit tests will pass if you re-execute `stack test`. If you want to start with a clean slate, stop your Elasticsearch instance, delete the `data/` folder in the Elasticsearch installation, restart Elasticsearch, and re-run `stack test`.+To run the tests:+1. Get into the Nix environment by running `nix develop` (or `nix-shell` for a non-flake setup)+1. Start Elasticsearch defined by `docker-compose.yml`: `make compose`+1. Run the tests with Cabal: `cabal test`++The second step can be left out if ElasticSearch (or OpenSearch) is started manually. Contributions -------------
bloodhound.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.4 name: bloodhound-version: 0.23.0.0+version: 0.23.0.1 synopsis: Elasticsearch client library for Haskell description: Elasticsearch made awesome for Haskell hackers category: Database, Search@@ -16,7 +16,7 @@ extra-doc-files: README.md changelog.md-tested-with: GHC==9.6.2, GHC==9.4.5, GHC==9.2.7, GHC==9.0.2, GHC==8.10.7+tested-with: GHC==8.10.7, GHC==9.0.2, GHC==9.2.8, GHC==9.4.8, GHC==9.6.6, GHC==9.8.4, GHC==9.10.1, GHC==9.12.1 source-repository head@@ -146,6 +146,8 @@ TestsUtils.Generators TestsUtils.Import Paths_bloodhound+ autogen-modules:+ Paths_bloodhound hs-source-dirs: tests ghc-options: -Wall -fno-warn-orphans@@ -199,6 +201,11 @@ type: exitcode-stdio-1.0 hs-source-dirs: tests main-is: Doctests.hs+ autogen-modules:+ Paths_bloodhound+ other-modules:+ Paths_bloodhound+ default-language: Haskell2010 ghc-options: -threaded build-depends: aeson
changelog.md view
@@ -1,3 +1,14 @@+0.23.0.1+========+- @arybczak+ - add GHC 9.10/9.12 support+- @supersvan+ - chore: Improve Haddock of `isVersionConflict`+ - chore: Add test to check response predicates+- @blackheaven+ - chore: migrate CI from `Haskell-CI` to `get-checked`+ - fix: various bugfixes+ 0.23.0.0 ======== - @blackheaven
src/Database/Bloodhound/Internal/Client/BHRequest.hs view
@@ -304,7 +304,7 @@ eitherDecodeResponse = eitherDecode . responseBody . getResponse -- | Was there an optimistic concurrency control conflict when--- indexing a document?+-- indexing a document? (Check '409' status code.) isVersionConflict :: BHResponse parsingContext a -> Bool isVersionConflict = statusCheck (== 409) @@ -390,11 +390,26 @@ mempty = EsError Nothing "Monoid value, shouldn't happen" instance FromJSON EsError where- parseJSON (Object v) =- EsError- <$> v- .:? "status"- <*> (v .: "error" <|> (v .: "error" >>= (.: "reason")))+ parseJSON (Object v) = p1 <|> p2 <|> p3+ where+ p1 =+ EsError+ <$> v .:? "status"+ <*> v .: "error"+ p2 =+ EsError+ <$> v .:? "status"+ <*> (v .: "error" >>= (.: "reason"))+ p3 = do+ failures <- v .: "failures"+ -- This is a bit imprecise: We're only using the first error, ignoring+ -- all others.+ case failures of+ (failure : _) ->+ EsError+ <$> failure .:? "status"+ <*> (failure .: "cause" >>= (.: "reason"))+ [] -> fail "could not find field `failure`" parseJSON _ = empty -- | 'EsProtocolException' will be thrown if Bloodhound cannot parse a response
src/Database/Bloodhound/Internal/Versions/Common/Types/Newtypes.hs view
@@ -324,9 +324,9 @@ check "Is empty" $ not $ T.null name check "Is longer than 255 bytes" $ BS.length (T.encodeUtf8 name) < 256 check "Contains uppercase letter(s)" $ T.all (\x -> not (isLetter x) || isLower x) name- check "Includes [\\/*?\"<>| ,#:]" $ T.all (flip @_ @String notElem "\\/*?\"<>| ,#:") name+ check "Includes [\\/*?\"<>| ,#:]" $ T.all (flip notElem ("\\/*?\"<>| ,#:" :: String)) name check "Is (.|..)" $ notElem name [".", ".."]- check "Starts with [-_+.]" $ maybe False (flip @_ @String notElem "-_+." . fst) $ T.uncons name+ check "Starts with [-_+.]" $ maybe False (flip notElem ("-_+." :: String) . fst) $ T.uncons name return $ IndexName name mkIndexNameSystem :: Text -> Either Text IndexName@@ -335,8 +335,8 @@ check "Is empty" $ not $ T.null name check "Is longer than 255 bytes" $ BS.length (T.encodeUtf8 name) < 256 check "Contains uppercase letter(s)" $ T.all (\x -> not (isLetter x) || isLower x) name- check "Includes [\\/*?\"<>| ,#:]" $ T.all (flip @_ @String notElem "\\/*?\"<>| ,#:") name- check "Starts with [-_+]" $ maybe False (flip @_ @String notElem "-_+" . fst) $ T.uncons name+ check "Includes [\\/*?\"<>| ,#:]" $ T.all (flip notElem ("\\/*?\"<>| ,#:" :: String)) name+ check "Starts with [-_+]" $ maybe False (flip notElem ("-_+" :: String) . fst) $ T.uncons name return $ IndexName name qqIndexName :: QuasiQuoter
tests/Test/DocumentsSpec.hs view
@@ -38,6 +38,21 @@ Right (res', _) -> liftIO $ isVersionConflict res' `shouldBe` True Left e -> liftIO $ errorStatus e `shouldBe` Just 409 + it "can use predicates on the response" $+ withTestEnv $ do+ let ev = ExternalDocVersion minBound+ let cfg = defaultIndexDocumentSettings {idsVersionControl = ExternalGT ev}+ resetIndex+ (res, _) <- insertData' cfg+ liftIO $ isCreated res `shouldBe` True+ liftIO $ isSuccess res `shouldBe` True+ liftIO $ isVersionConflict res `shouldBe` False++ res' <- insertData'' cfg+ liftIO $ isCreated res' `shouldBe` False+ liftIO $ isSuccess res' `shouldBe` False+ liftIO $ isVersionConflict res' `shouldBe` True+ it "indexes two documents in a parent/child relationship and checks that the child exists" $ withTestEnv $ do resetIndex
tests/Test/JSONSpec.hs view
@@ -81,6 +81,20 @@ flagStrs = T.splitOn "|" str in noDuplicates flagStrs + describe "FromJSON EsError" $ do+ it "should parse ElasticSearch 7 responses (status & error)" $ do+ let mbJson = decode "{\"status\": 209, \"error\": \"Error message\"}"+ mbJson `shouldBe` Just (EsError (Just 209) "Error message")++ it "should parse ElasticSearch 7 responses (error.reason)" $ do+ let mbJson = decode "{\"error\": {\"reason\": \"Error message\"}}"+ mbJson `shouldBe` Just (EsError Nothing "Error message")++ it "should parse OpenSearch 1.3 responses" $ do+ -- This is a real error response for a version conflict+ let mbJson = decode "{\"took\":9,\"timed_out\":false,\"total\":3,\"updated\":1,\"deleted\":0,\"batches\":1,\"version_conflicts\":2,\"noops\":0,\"retries\":{\"bulk\":0,\"search\":0},\"throttled_millis\":0,\"requests_per_second\":-1.0,\"throttled_until_millis\":0,\"failures\":[{\"index\":\"directory_test\",\"type\":\"_doc\",\"id\":\"9fda4188-2afd-490d-8796-e023df61a4e9\",\"cause\":{\"type\":\"version_conflict_engine_exception\",\"reason\":\"[9fda4188-2afd-490d-8796-e023df61a4e9]: version conflict, required seqNo [11], primary term [1]. current document has seqNo [16] and primary term [1]\",\"index\":\"directory_test\",\"shard\":\"0\",\"index_uuid\":\"Y3RpVY_DQEW9ULn8oGulrg\"},\"status\":409},{\"index\":\"directory_test\",\"type\":\"_doc\",\"id\":\"d70b631d-966a-4951-a94c-35ddc210f28a\",\"cause\":{\"type\":\"version_conflict_engine_exception\",\"reason\":\"[d70b631d-966a-4951-a94c-35ddc210f28a]: version conflict, required seqNo [13], primary term [1]. current document has seqNo [15] and primary term [1]\",\"index\":\"directory_test\",\"shard\":\"0\",\"index_uuid\":\"Y3RpVY_DQEW9ULn8oGulrg\"},\"status\":409}]}"+ mbJson `shouldBe` Just (EsError (Just 409) "[9fda4188-2afd-490d-8796-e023df61a4e9]: version conflict, required seqNo [11], primary term [1]. current document has seqNo [16] and primary term [1]")+ describe "Exact isomorphism JSON instances" $ do propJSON (Proxy :: Proxy IndexName) propJSON (Proxy :: Proxy DocId)
tests/TestsUtils/Common.hs view
@@ -205,6 +205,13 @@ _ <- performBHRequest $ refreshIndex testIndex return r +-- | Returns the `BHResponse` of `indexDocument` without any parsing+insertData'' :: IndexDocumentSettings -> BH IO (BHResponse StatusDependant IndexedDocument)+insertData'' ids = do+ r <- dispatch $ indexDocument testIndex ids exampleTweet (DocId "1")+ _ <- performBHRequest $ refreshIndex testIndex+ return r+ insertTweetWithDocId :: Tweet -> Text -> BH IO IndexedDocument insertTweetWithDocId tweet docId = do let ids = defaultIndexDocumentSettings