wrangling the internet of things with haskell production
play

wrangling the internet of things with haskell production haskell - PowerPoint PPT Presentation

wrangling the internet of things with haskell production haskell Reid Draper @reiddraper production haskell Reid Draper @reiddraper production haskell today production haskell at helium 12 months in lowest defect rate lowest defect rate


  1. wrangling the internet of things with haskell production haskell Reid Draper @reiddraper

  2. production haskell Reid Draper @reiddraper

  3. production haskell today

  4. production haskell at helium 12 months in

  5. lowest defect rate

  6. lowest defect rate easiest to refactor

  7. lowest defect rate easiest to refactor most enjoyable OSS libraries for everything*

  8. 20k LOC

  9. 20k LOC 5 developers

  10. 20k LOC 5 developers 6 production services

  11. build deploy monitor test develop

  12. build deploy monitor test develop

  13. cabal hell

  14. cabal hell

  15. stack haskellstack.org

  16. ghc packages snapshot project specific

  17. 20k LOC 2 seconds

  18. ordeal github.com/reiddraper/ordeal

  19. stack build self-contained executable

  20. build deploy monitor test develop

  21. app ��� assets � ��� images � � ��� favicon.ico � ��� javascript � � ��� site.js � ��� stylesheet � ��� site.css ��� bin ��� app

  22. tar -xzf app-370b347.tgz ln -s app-370b347 current restart app

  23. ln -s app-83181ad current restart app

  24. 60MB

  25. build deploy monitor test develop

  26. ekg

  27. stdout file syslog

  28. build deploy monitor test develop

  29. QuickCheck

  30. propEvent :: Event -> Bool propEvent a = Just a == decode (encode a)

  31. Event roundtrips in JSON: FAIL (0.04s) *** Failed! Falsifiable (after 1 test): Event {_severity = Error, _facility = Unspecified, _sampled = 1894-02-22 00:00:04.5986 UTC, _eventDetails = ElementDisconnect {_elementMAC = 8ec52584b2c82424}, _eventMessage = Nothing, _originator = http://www.ietf.org/rfc/rfc2396.txt, _reference = Just http://www.ietf.org/rfc/rfc2396.txt }

  32. Event roundtrips in JSON: FAIL (0.04s) *** Failed! Falsifiable (after 1 test): Event {_severity = Error, _facility = Unspecified, _sampled = 1894-02-22 00:00:04.5986 UTC, _eventDetails = ElementDisconnect {_elementMAC = 8ec52584b2c82424}, _eventMessage = Nothing, _originator = http://www.ietf.org/rfc/rfc2396.txt, _reference = Just http://www.ietf.org/rfc/rfc2396.txt }

  33. ghci> t 1894-02-22 00:00:04.5986 UTC ghci> Data.Aeson.encode t "\"1894-02-22T00:00:04.598Z\""

  34. build deploy monitor test develop

  35. postgresql-transactional github.com/helium/postgresql-transactional

  36. lookupUser emailAddress = queryFirst [emailAddress] [sql| SELECT id, email, name, timezone FROM user_account 
 WHERE email = ? |]

  37. foo

  38. foo bar

  39. foo bar baz

  40. quz foo bar baz

  41. quz foo bar baz buz

  42. fiz quz foo bar baz buz

  43. BEGIN BEGIN COMMIT COMMIT

  44. BEGIN BEGIN COMMIT COMMIT

  45. BEGIN BEGIN COMMIT COMMIT

  46. WARNING: there is already a transaction in progress WARNING: there is no transaction in progress

  47. fiz quz foo bar baz buz

  48. fiz quz foo bar baz buz

  49. quz foo bar baz buz

  50. lookupUser :: Connection -> Text -> IO (Maybe User) lookupUser connection emailAddress = queryFirst [emailAddress] [sql| SELECT id, email, name, timezone FROM user_account 
 WHERE email = ? |] connection

  51. createUser :: Connection -> NewUser -> IO User createOrganization :: Connection -> NewOrganization -> IO Organization addUserToOrganization :: Connection -> User -> Organization -> IO ()

  52. createUserAndOrganization :: Connection -> NewUser -> IO () createUserAndOrganization connection newUser = withTransaction connection $ do let newOrganization = NewOrganization (newUser ^. name) user <- createUser connection newUser org <- createOrganization connection newOrganization addUserToOrganization connection user org

  53. -- NOTE: you MUST wrap this in a transaction!! createUserAndOrganization :: Connection -> NewUser -> IO () createUserAndOrganization connection newUser = do let newOrganization = NewOrganization (newUser ^. name) user <- createUser connection newUser org <- createOrganization connection newOrganization addUserToOrganization connection user org

  54. withTransaction conn $ do createUserAndOrganization conn newUser somethingElse conn

  55. types to the rescue

  56. lookupUser :: Connection -> Text -> IO (Maybe User) lookupUser :: Text -> PGTransaction (Maybe User)

  57. runPGTransaction :: PGTransaction a -> Postgres.Connection -> IO a

  58. createUserAndOrganization :: NewUser -> PGTransaction () createUserAndOrganization newUser = let newOrganization = NewOrganization (newUser ^. name) user <- createUser newUser org <- createOrganization newOrganization addUserToOrganization user org foo = do createUserAndOrganization newUser somethingElse runPGTransaction foo connection

  59. notAllowed = do user <- createUser newUser someSlowSideEffectingThing return user

  60. notAllowed = do user <- createUser newUser someSlowSideEffectingThing :: IO () return user

  61. postgresql-transactional github.com/helium/postgresql-transactional

  62. build deploy monitor test develop

  63. Reid Draper @reiddraper github.com/helium helium.com

Recommend


More recommend