Skip to content

Commit

Permalink
prepare 3.1.1 release (#52)
Browse files Browse the repository at this point in the history
* initial implementation

* [ch57654] add circleci config (#3)

* [ch57656] cleanup dependencies (#2)

* [ch57662] Add repo templates (#5)

* [ch57657] Add setters for User and Config (#4)

* [ch57663] Only expose public modules in package

* [ch57666] Add Haddock (#7)

* log on authentication failure (#8)

* [ch57685] cleanup package (#9)

* [ch57695] metric event logic (#10)

* [ch58006] Hide typeclass instances with newtype public API (#11)

* fix contributor guide wrong link (#12)

* fix minor title-casing inconsistencies (#13)

* git ignore + re-ordering lists (#14)

* adding .gitignore

* re-ordering items

* fix typos

* [ch58315] Add OSX CI (#15)

* updated build instructions (#16)

* [tickets listed in body] Add misc configuration and close. (#17)

[ch58083] add close
[ch58076] make connection timeout configuration
[ch58072] add offline mode
[ch58435] make event sending configurable

* set version string to 0.1.0 (#18)

* add beta warning

* [ch58816] Fix user agent format, prepare release

* [ch59631] add haskell sdk to releaser (#20)

* [ch63561] Store V2 Interface (#21)

* [ch63772] Mock store interface tests (#22)

* [ch58074] Redis store implementation (#23)

* Linting and some refactoring of streaming code.

* [ch64438] dont send empty event payloads

* [ch43307] use last bucket as fallback

* Increased test coverage (#28)

* Custom serialization instances when using custom deserialization (#29)

* [ch64640] Add support for Ldd (#30)

* [ch65827] payload uuid and event send retry (#32)

* [ch66643] strict fields

* [ch67127] minimal version constraints (#34)

* [ch67145] update master export list

* [ch67148] Some doc typos (#36)

* [ch67154] Remove beta warning

* [ch67570] actually use store initialization status (#38)

* [ch69091] Add SSE timeout, fix streaming CPU burn (#39)

* [ch70425] standardize streaming behavior (#41)

* [ch73995] remove null user key support (#42)

* [ch76243] update sdk range for redis

* [ch92127] remove sel field from flag model

* Removed the guides link

* [ch99749] add alias and update event logic (#45)

* merge traffic allocation changes

* Updates docs URLs (#47)

* Use non-deprecated CircleCI Xcode image. (#48)

* Path is optional; should default to / (#53)

* Create index event when calling track (#51)

* Conditionally index users when processing eval events (#56)

* Trim trailing slashes from URIs (#52)

* Add event summary regardless of capacity (#55)

* Do not emit identify event if key is empty; notice user otherwise (#50)

If the provided user key is empty, we do not want to emit an identify
event. We will log a warning message to the customer instead.

If a valid user has been provided though, not only should we emit the
event, but also we should add that user to the LRU cache so that we
don't unnecessarily generate future index events.

* Support for both aeson < 2 and aeson > 2

* Unknown flags should return provided default value (#57)

* Exclude various fields from JSON payload if not required (#54)

* Adds links to Relay Proxy docs

* Add support for client side availability (#61)

* Add new all flags state method (#62)

* Add initial structure for SDK test harness (#63)

* Fix test if user attribute is null (#65)

* Fix negative index evaluation (#66)

* Track last known server time (#67)

* Introduce File and Test Data Sources (#68)

* Fix aeson 2.0 compatibility (#69)

A user submitted contribution was merged to support Aeson 2.0. While
all of our tests were passing, this was because we lacked a test
environment that actually used 2.0

This commit addresses the remaining compatibility changes and
introduces a later test environment to ensure we are actually building
with Aeson 2.0 support.

* Bump resource class for linux builds (#70)

* Add cabal file and ignore dist-newstyle. (#44)

* Add CI support for cabal and hlint (#71)

A customer recently provided two pull requests -- one to add the
generated cabal file to our repository and the second to update our
hlint configuration file.

While great, these change aren't sufficient because

- We have no way to enforce the generated cabal file is up to date
- We aren't running hlint during the CI process

This commit introduces CI behaviors to resolve both of these issues.

* Update releaser config to use docker instead of circleci (#72)

* Update releaser configuration (#73)

In a previous commit I updated the releaser config. However, I failed to
adjust two additional bits of configuration.

- The repository now includes a cabal file which contains version
  information. We will now update that.
- docs need to be copied into the appropriate releaser directory for the
  GH pages branch to be updated correctly.

* Speed up Haskell builds for OSX (#74)

The OSX builds have been taking a very long time, despite doing less
work than the Linux equivalents. A little digging has uncovered
incorrect CI caching for the OSX builds.

This small change has taken the build from approximately 45m to 9m per
OSX run.

* Expand upper versions on select packages (#77)

A customer contributed this fix. I made some minor tweaks, but testing
seems to indicate everything works as expected.

Co-authored-by: Veronika Romashkina <vrom911@gmail.com>

* Add application info support (#89)

* Match package requirements to SDK (#105)

When we bumped the version numbers for the v3 release, we didn't bump
the corresponding versions in the redis store.

We didn't catch this because we don't try to build the redis package in
CI, and we certainly don't try to build it against every supported Stackage
resolver.

For now, I've taken the simplest solution to get some tests confirming
the behavior. Once I merge this forward in the v4 branch, I will look at
simplifying a lot of the redundancy that exists in our unit tests.

* Stop polling when unrecoverable (#107)

* Add branch configuration in preparation of v4 release (#113)

---------

Co-authored-by: hroederld <hroeder@launchdarkly.com>
Co-authored-by: Ben Woskow <48036130+bwoskow-ld@users.noreply.github.com>
Co-authored-by: Gavin Whelan <gwhelan@launchdarkly.com>
Co-authored-by: LaunchDarklyCI <dev@launchdarkly.com>
Co-authored-by: ember-stevens <79482775+ember-stevens@users.noreply.github.com>
Co-authored-by: Matthew M. Keeler <keelerm84@gmail.com>
Co-authored-by: Alex Biehl <alex@scarf.sh>
Co-authored-by: Matthew M. Keeler <mkeeler@launchdarkly.com>
Co-authored-by: Ember Stevens <ember.stevens@launchdarkly.com>
Co-authored-by: Louis Chan <lchan@launchdarkly.com>
Co-authored-by: LaunchDarklyReleaseBot <launchdarklyreleasebot@launchdarkly.com>
Co-authored-by: Phil de Joux <philderbeast@gmail.com>
Co-authored-by: Veronika Romashkina <vrom911@gmail.com>
  • Loading branch information
14 people committed Feb 17, 2023
1 parent 9ea8c74 commit d20159f
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 28 deletions.
9 changes: 7 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,13 @@ jobs:
name: Resolve/Update Dependencies
command: stack --no-terminal setup
- run:
name: Build
name: Build library
command: stack --no-terminal build
- run:
name: Build Redis store
command: |
cd ./stores/launchdarkly-server-sdk-redis/
stack --no-terminal build
- run:
name: Install and run hlint
command:
Expand Down Expand Up @@ -143,7 +148,7 @@ jobs:
command: |
cd ..
cabal update
cabal install hpack-0.35.0
cabal install hpack-0.35.1
cd -
- run:
name: Verify the generated .cabal file is up-to-date
Expand Down
4 changes: 4 additions & 0 deletions .ldrelease/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ repo:
public: haskell-server-sdk
private: haskell-server-sdk-private

branches:
- name: main
- name: 3.x

jobs:
# Have no fear! This is the officially sanctioned image as seen at
# https://docs.haskellstack.org/en/stable/docker_integration/#image-repositories
Expand Down
7 changes: 7 additions & 0 deletions src/LaunchDarkly/Server/Network/Common.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module LaunchDarkly.Server.Network.Common
, tryHTTP
, addToAL
, handleUnauthorized
, isHttpUnrecoverable
) where

import Data.ByteString.Internal (unpackChars)
Expand Down Expand Up @@ -56,3 +57,9 @@ getServerTime response
where headers = responseHeaders response
date = fromMaybe "" $ lookup hDate headers
parsedTime = parseTimeM True defaultTimeLocale rfc822DateFormat (unpackChars date)

isHttpUnrecoverable :: Int -> Bool
isHttpUnrecoverable status
| status < 400 || status >= 500 = False
| status `elem` [400, 408, 429] = False
| otherwise = True
58 changes: 42 additions & 16 deletions src/LaunchDarkly/Server/Network/Polling.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ import Data.Text (Text)
import qualified Data.Text as T
import Network.HTTP.Client (Manager, Request(..), Response(..), httpLbs)
import Data.Generics.Product (getField)
import Control.Monad (forever)
import Control.Concurrent (threadDelay)
import Data.Aeson (eitherDecode, FromJSON(..))
import Control.Monad.Logger (MonadLogger, logInfo, logError)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Control.Monad.Catch (MonadMask, MonadThrow)
import Network.HTTP.Types.Status (ok200)
import Network.HTTP.Types.Status (ok200, Status (statusCode))

import LaunchDarkly.Server.Network.Common (checkAuthorization, tryHTTP, handleUnauthorized)
import LaunchDarkly.Server.Network.Common (checkAuthorization, tryHTTP, handleUnauthorized, isHttpUnrecoverable)
import LaunchDarkly.Server.Features (Flag, Segment)
import LaunchDarkly.AesonCompat (KeyMap)

Expand All @@ -23,33 +22,60 @@ import LaunchDarkly.Server.DataSource.Internal (DataSourceUpdates(..))
import LaunchDarkly.Server.Config.ClientContext
import LaunchDarkly.Server.Client.Internal (Status(..))
import LaunchDarkly.Server.Config.HttpConfiguration (HttpConfiguration(..), prepareRequest)
import Data.ByteString.Lazy (ByteString)

data PollingResponse = PollingResponse
{ flags :: !(KeyMap Flag)
, segments :: !(KeyMap Segment)
} deriving (Generic, FromJSON, Show)

processPoll :: (MonadIO m, MonadLogger m, MonadMask m, MonadThrow m) => Manager -> DataSourceUpdates -> Request -> m ()
processPoll :: (MonadIO m, MonadLogger m, MonadMask m, MonadThrow m) => Manager -> DataSourceUpdates -> Request -> m Bool
processPoll manager dataSourceUpdates request = liftIO (tryHTTP $ httpLbs request manager) >>= \case
(Left err) -> $(logError) (T.pack $ show err)
(Right response) -> checkAuthorization response >> if responseStatus response /= ok200
then $(logError) "unexpected polling status code"
else case (eitherDecode (responseBody response) :: Either String PollingResponse) of
(Left err) -> $(logError) (T.pack $ show err)
(Left err) -> do
$(logError) (T.pack $ show err)
pure True
(Right response) -> checkAuthorization response >> processResponse response

where

processResponse :: (MonadIO m, MonadLogger m, MonadMask m, MonadThrow m) => Response ByteString -> m Bool
processResponse response
| isHttpUnrecoverable $ statusCode $ responseStatus response = do
$(logError) "polling stopping after receiving unrecoverable error"
pure False
| responseStatus response /= ok200 = do
$(logError) "unexpected polling status code"
pure True
| otherwise = case (eitherDecode (responseBody response) :: Either String PollingResponse) of
(Left err) -> do
$(logError) (T.pack $ show err)
pure $ True
(Right body) -> do
status <- liftIO $ dataSourceUpdatesInit dataSourceUpdates (getField @"flags" body) (getField @"segments" body)
case status of
Right () -> liftIO $ dataSourceUpdatesSetStatus dataSourceUpdates Initialized
Left err ->
Right () -> do
liftIO $ dataSourceUpdatesSetStatus dataSourceUpdates Initialized
pure $ True
Left err -> do
$(logError) $ T.append "store failed put: " err
pure $ True




pollingThread :: (MonadIO m, MonadLogger m, MonadMask m) => Text -> Natural -> ClientContext -> DataSourceUpdates -> m ()
pollingThread baseURI pollingIntervalSeconds clientContext dataSourceUpdates = do
let pollingMicroseconds = fromIntegral pollingIntervalSeconds * 1000000
req <- liftIO $ prepareRequest (httpConfiguration clientContext) (T.unpack baseURI ++ "/sdk/latest-all")
handleUnauthorized dataSourceUpdates $ forever $ do
req <- liftIO $ prepareRequest (httpConfiguration clientContext) (T.unpack baseURI ++ "/sdk/latest-all")
handleUnauthorized dataSourceUpdates $ (poll req pollingMicroseconds)

where

poll :: (MonadIO m, MonadLogger m, MonadMask m) => Request -> Int -> m ()
poll req pollingMicroseconds = do
$(logInfo) "starting poll"
processPoll (tlsManager $ httpConfiguration clientContext) dataSourceUpdates req
$(logInfo) "finished poll"
liftIO $ threadDelay pollingMicroseconds
processPoll (tlsManager $ httpConfiguration clientContext) dataSourceUpdates req >>= \case
True -> do
liftIO $ threadDelay pollingMicroseconds
poll req pollingMicroseconds
False -> pure ()
4 changes: 0 additions & 4 deletions stack.yaml

This file was deleted.

1 change: 1 addition & 0 deletions stack.yaml
12 changes: 6 additions & 6 deletions stores/launchdarkly-server-sdk-redis/package.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: launchdarkly-server-sdk-redis
version: 0.1.0
version: 0.1.1
github: "launchdarkly/haskell-server-sdk"
license: Apache-2.0
license-file: "LICENSE"
Expand All @@ -13,15 +13,15 @@ category: Web
description: Please see the README on GitHub at <https://github.com/launchdarkly/haskell-server-sdk#readme>

dependencies:
- aeson >=1.4.4.0 && <1.5
- aeson >=1.4.4.0 && <1.6 || >= 2.0.1.0 && <2.2
- base >=4.7 && <5
- bytestring >=0.10.8.2 && <0.11
- bytestring >=0.10.8.2 && <0.12
- bytestring-conversion >=0.3.1 && <0.4
- exceptions >=0.10.2 && <0.11
- generic-lens >=1.1.0.0 && <1.2
- hedis >=0.12.7 && <0.13
- generic-lens >=1.1.0.0 && <2.3
- hedis >=0.12.7 && <0.16
- launchdarkly-server-sdk >=1.0.0 && <4.0.0
- text >=1.2.3.1 && <1.3
- text >=1.2.3.1 && <2.1
- unordered-containers >=0.2.10.0 && <0.3

default-extensions:
Expand Down
7 changes: 7 additions & 0 deletions stores/launchdarkly-server-sdk-redis/stack-lts-14.1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
resolver: lts-14.1

packages:
- .

extra-deps:
- ../../
7 changes: 7 additions & 0 deletions stores/launchdarkly-server-sdk-redis/stack-lts-16.31.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
resolver: lts-16.31

packages:
- .

extra-deps:
- ../../
7 changes: 7 additions & 0 deletions stores/launchdarkly-server-sdk-redis/stack-lts-18.27.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
resolver: lts-18.27

packages:
- .

extra-deps:
- ../../
7 changes: 7 additions & 0 deletions stores/launchdarkly-server-sdk-redis/stack-lts-19.13.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
resolver: lts-19.13

packages:
- .

extra-deps:
- ../../

0 comments on commit d20159f

Please sign in to comment.