SlideShare ist ein Scribd-Unternehmen logo
1 von 70
Joys & frustrations of putting
34,000 lines of Haskell into production
NOTE: Another version of these slides (with more text) is available at
https://www.slideshare.net/saurabhnanda/joys-frustrations-of-putting-34000-lines-
of-haskell-into-production-at-vacation-labs
Haskell
Source of all this gyaan
34,000 LoC of Haskell in production
Touched (almost) all aspects of a typical web-app stack
Except Haskell (or Purescript) in the frontend.
Using Angular2 + TypeScript instead.
Why Haskell?Why Haskell?
आ बैल मुझे मारआ बैल मुझे मार
Vacation Labs
Travel-Commerce Platform
Enabling travel companies with e-commerce technology.
Built mostly with Rails & Angular-v1 (Javascript)
Remember those numbers
“It's always good to remember where you come from and
celebrate it. To remember where you come from is part of
where you're going.”
- Anthony Burgess
Problems with Rails/JS
Code
Unable to refactor core data-structures confidently
Unable to remove dead-code without fear of breaking
Unable to review code effectively
Building webapps in Haskell
is harder than it ought to be
What I felt a year ago, just starting out...
http://tinyurl.com/haskell-is-needlessly-hard
Haskell.
First, the GOOD parts.
factoringre
actoringref
ctoringrefa
toringrefac
refactoring
toringrefact
oringrefacto
ingrefactor
ngrefactori
{ “Type-safe” : “JSON” }
Aeson is brilliant. Auto-derives a lot of boilerplate.
OTOH writing JSON codecs in TypeScript by hand.
HTTP / Web / App Server
WAI/Warp has pretty good performance.
One lightweight thread per-incoming request.
Solid concurrency without an event-driven / callback model
(unlike node).
Now, for the
BAD parts.
Big problems faced first-hand
Library eco-system is effectively broken
Lack of established best-practices
Editor tooling
Records
Lack of ORM
Library ecosystem is
effectively broken
Lack of libraries it NOT a problem
Fragmentation, non-standardization
Heaps of cruft on Hackage
Broken library ecosystem
I can easily compare Haskell libraries
to select the best one
Strongly
disagree
Disagree Neutral Agree Strongly
agree
100
200
300
400
500
I can easily compare Haskell libraries
to select the best one
Strongly
disagree
Disagree Neutral Agree Strongly
agree
100
200
300
400
500
44% respondents
replied negatively
Emails
SES, Postmark, Mandrill, raw SMTP, etc. All there.
Fiasco with `smtp-mail` library.
Broken library ecosystem
Sendgrid library
`haskell-sendgrid` is incomplete. We wrote our own.
Ping us on Twitter if you want to help open-source our
code. (Open bounty)
http://www.vacationlabs.com/haskell-bounty-program/
Call for contribution
Testing
287 packages related to testing
None of them runs tests in isolated DB txns out-of-the-box.
Broken library ecosystem
DB libraries
persistent, hedgehog, hasql, pg-simple, opaleye,
mysql-simple, HaskellDB
Which to use when? Why so many?
Broken library ecosystem
Lack of established
best-practices
Community keeps arguing about core stuff
stack vs cabal
mtl vs free-monads
error handling
Is TH good or bad?
No best practices
Installing Haskell
FOUR different ways to install Haskell - seriously?!
PS: Just use “stack” - tried & tested. LTS snapshots are
awesome!
No best practices
Error handling
EIGHT different ways. Each library uses something else.
http://www.randomhacks.net/2007/03/10/haskell-8-ways-to-report-errors/
`ExceptT` vs `Conrol.Monad.Catch` fiasco
No best practices
do
x <- runExceptT (liftIO $ throwIO DivideByZero)
case x of
Left e -> pure “exception caught”
Right r -> pure “should never happen!”
do
x <- runExceptT (liftIO $ throwIO DivideByZero)
case x of
Left e -> pure “exception caught”
Right r -> pure “should never happen!”
-- OUTPUT
*** Exception: divide by zero
-- Reaction: Wtf ?!
do
x <- Control.Monad.Catch.try (liftIO $ throwIO DivideByZero)
case x of
Left (e :: SomeException) -> pure “exception caught”
Right r -> pure “should never happen!”
do
x <- Control.Monad.Catch.try (liftIO $ throwIO DivideByZero)
case x of
Left (e :: SomeException) -> pure “exception caught”
Right r -> pure “should never happen!”
-- OUTPUT
“exception caught”
Error reporting
Haskell code throws runtime errors. Please report them
properly.
Hype - “if it compiles, it runs”. Reality - “after a refactor, if it
compiles, then there is a high chance that you haven’t
broken anything”
No best practices
Which file?
Turns out “fastLogger” was trying to open a log-file in a non-existent
directory. (On LTS-9.0)
*** Exception: UnexpectedNull
{ errSQLType = “varchar”
, errSQLTableOid = Just (Oid 603560)
, errSQLField = “result22_2”
, errHaskellType = “Text”
, errMessage = “”
}
*** Exception: UnexpectedNull
{ errSQLType = “varchar”
, errSQLTableOid = Just (Oid 603560)
, errSQLField = “result22_2”
, errHaskellType = “Text”
, errMessage = “”
}
Which row? What SQL was being run?
Any other info that can help me debug this? Stacktrace?
Occurred during stress testing of JSON API. Wasted a lot of time!
Which file descriptor? Which library was accessing it? Nothing!
Turned out that DB pool size was larger than what DB could handle.
Absence of CallStacks can
probably be fixed
Call for contribution
Imperceptible perf-penalty with HasCallStack in IO code
Not being used by IO-heavy libraries. Raise some PRs!
GHC discussion to infer HasCallStack automatically
https://ghc.haskell.org/trac/ghc/ticket/13360
Testing
We drank the QuickCheck kool-aid
QuickCheck fiasco
No best practices
Editor tooling
SAD TRUTH - Nothing works as well as it should.
Tried a lot of things
Emacs + haskell-mode, Spacemacs + Intero, SublimeHaskell, Haskero, Haskelly, HIE, ghcid, etc.
Underlying GHCi hogs/leaks memory.
Editor tooling
Important caveat about
memory usage
Haskell DOES NOT leak memory in production.
Only present in GHC-i -- used in development.
Production Rails-app: 360 MB of RSS (x 3 processes)
Production Haskell-app: 78 MB of RSS (single process).
Recommendation:
Editor tooling
Use spacemacs + intero OR VSCode + HIE (Haskell IDE
Engine)
Keep ghci open in a terminal window and make friends with
:set -fobject-code & :load & :reload
Shout-out to
HIE (Haskell IDE Engine)
Call for contribution
Please use it, if it works for you. Make it work for you!
Contribute if you can.
https://github.com/haskell/haskell-ide-engine
Broken record
Records. Records. Records.
Records in Haskell are beyond horrible.
Some say, Haskell doesn’t even have records.
http://www.parsonsmatt.org/overcoming-records/
-- Your `users` table would probably map to the following…
data User = User
{ userId :: UserId
, userCreatedAt :: UTCTime
, userUpdatedAt :: UTCTime,
, userStatus :: UserStatus,
, userName :: Maybe Text
, userEmail :: Text
, userAge :: Maybe Int
}
-- But, you can’t use this in your `createUser` endpoint.
-- UI shouldn’t set `id, createdAt, updatedAt, status`
-- No easy way to create a “sub-record” from a master record.
-- Created our own library `record-splicer` to deal with this...
createRecordSplice SpliceArgs
{
sourcePrefix = "user"
, source = ''User
, requiredFields =
[
'userName
, 'userEmail
, 'userAge
]
, targetPrefix = "newuser"
, targetName = "NewUser"
, deriveClasses = [''Eq, ''Show, ''Generic]
}
makeLensesWith abbreviatedFields ''NewUser
// Same thing in TypeScript
type interface User {
readonly id: number
, readonly createdAt: DateTime
, readonly updatedAt: DateTime
, readonly status: ‘unconfirmed’ | ‘confirmed’ | ‘blocked’
, readonly name: string | null
, readonly email: string
, readonly age: string | null
}
// Making a typesafe sub-record
type NewUser = Pick <User, ‘name’ | ‘email’ | ‘age’>;
// Making a typesafe super-record
type Admin extends User {
readonly permissions: Array<Permission>
}
DB Library.
Dare I say ORM?
Either you use an ORM or you write an ad-hoc ORM.
Tried to understand how to build apps without an ORM.
Not convinced. At all. [1] [2] [3] [4]
Lack of ORM
Associations?
No DB library deals with associations.
Except two new discoveries - beam & postgresql-orm
Lack of ORM
Validations?
No DB library deals with validations.
Rails’ convention of putting strict invariants/validations in
the DB layer works ridiculously well.
Lack of ORM
Validations in DB-layer are an
anti-pattern?
Let’s look state-of-the-art: “digestive-functors”
Lack of ORM
DB Library Problem as well.
Incomplete / half-baked DB libraries
mysql-simple - (had?) concurrency issues
postgresql-simple doesn’t use PREPARE/EXECUTE
Opaleye generates slow queries
Lack of ORM
Applicative parsers?
Or “Hodor” parsers.
Special hate for applicative parsers!
Negate all benefits of static typing.
Especially true for postgresql-simple.
Lack of ORM
query_ = ([qc|
SELECT
c.id as client_id
, coalesce(c.custom_domain, c.domain) as domain
, c.home_page as home_page
, c.support_phone as support_phone
, c.support_email as support_email
, c.logo_photo_id as loto_photo_id
, logo_photo.image_file_name as logo_file_name
, logo_photo.image_fingerprint as logo_fingerprint
, c.favicon_image_id as favicon_image_id
, favicon.image_file_name as favicon_file_name
…
query_ = ([qc|
SELECT
c.id as client_id
, coalesce(c.custom_domain, c.domain) as domain
, c.home_page as home_page
, c.support_phone as support_phone
, c.support_email as support_email
, c.logo_photo_id as loto_photo_id
, logo_photo.image_file_name as logo_file_name
, logo_photo.image_fingerprint as logo_fingerprint
, c.favicon_image_id as favicon_image_id
, favicon.image_file_name as favicon_file_name
…
rowParser assetHost_ = Storefront
<$> field <*> field <*> field <*> field <*> field
<*> (photoEssentialsParser assetHost_ Photo.WebsiteLogo)
<*> (photoEssentialsParser assetHost_ Photo.Favicon)
<*> field <*> field <*> field <*> field <*> field <*> field
<*> field <*> field <*> field <*> field <*> field <*> field
<*> field <*> field <*> hstoreBoolParser <*> field
<*> field <*> field <*> field <*> field <*> field <*> field
query_ = ([qc|
SELECT
c.id as hodor
, coalesce(c.custom_domain, c.domain) as hodor
, c.home_page as hodor
, c.support_phone as hodor
, c.support_email as hodor
, c.logo_photo_id as hodor
, logo_photo.image_file_name as hodor
, logo_photo.image_fingerprint as hodor
, c.favicon_image_id as hodor
, favicon.image_file_name as hodor
…
rowParser assetHost_ = Storefront
<$> hodor <*> hodor <*> hodor <*> hodor <*> hodor
<*> (photoEssentialsParser assetHost_ Photo.WebsiteLogo)
<*> (photoEssentialsParser assetHost_ Photo.Favicon)
<*> hodor <*> hodor <*> hodor <*> hodor <*> hodor <*> hodor
<*> hodor <*> hodor <*> hodor <*> hodor <*> hodor <*> hodor
<*> hodor <*> hodor <*> hstoreBoolParser <*> hodor
<*> hodor <*> hodor <*> hodor <*> hodor <*> hodor <*> hodor
PG-Simple’s “hodor” parser
can be fixed
There is an open bounty.
https://github.com/lpsmith/postgresql-simple/issues/43
http://www.vacationlabs.com/haskell-bounty-program
Call for contribution
What did we really build in
38,000 lines of Haskell?
Flexi-payment plugin
DelayedJob clone (but using LISTEN/NOTIFY) along with UI
Sendgrid library
Opaleye boilerplate code-generator
Deep instrumentation wrappers over core libs
Logging & Instrumentation
“Deep instrumentation” in Haskell seems to be non-existent
Eg. kind of stuff provided by Rails out of box, or Skylight, or New Relic
Very hard to build drop-in instrumentation libraries for Haskell.
Probably because of the type-system itself.
http://tinyurl.com/haskell-instrumentation
Built our own ad-hoc logging & instrumentation layer by
wrapping important libs
Job Queue
Rails has DelayedJob (with an RDBMS backend).
Works really well for moderate workloads. ACID compliant and doesn’t add more moving parts to production.
Couldn’t find anything similar in Haskell world. Built our own.
Will open-source.
Except `yesod-job-queue` but we aren’t using Yesod.
Redis & SQS job-queues available, but we didn’t use first-hand.
Can’t comment.
JobAdmin UI built by intern in 4 months (included learning Haskell).
Built using Servant, Lucid, Aeson, Opaleye.
Initial (excruciating) pain for long-term gain
We have already gone through the pain
Now, we are reaping the gains
Haskell sucks.
Why continue with it?
What’s next?
Raising awareness about the issues we faced.
The core language is not as confusing
as the ecosystem is.
Contributing in any way to fix the ecosystem.
Thank you
@saurabhnanda on twitter
@vacationlabs on instagram
Haskell Bounty Program
Haskell Internship Program
We’re hiring Haskellers (and Haskell enthusiasts)
 ABRIDGED VERSION - Joys & frustrations of putting 34,000 lines of Haskell into production (at Vacation Labs)

Weitere ähnliche Inhalte

Was ist angesagt?

Mito, a successor of Integral
Mito, a successor of IntegralMito, a successor of Integral
Mito, a successor of Integralfukamachi
 
Beyond JVM - YOW! Sydney 2013
Beyond JVM - YOW! Sydney 2013Beyond JVM - YOW! Sydney 2013
Beyond JVM - YOW! Sydney 2013Charles Nutter
 
Down the Rabbit Hole: An Adventure in JVM Wonderland
Down the Rabbit Hole: An Adventure in JVM WonderlandDown the Rabbit Hole: An Adventure in JVM Wonderland
Down the Rabbit Hole: An Adventure in JVM WonderlandCharles Nutter
 
Not Only Streams for Akademia JLabs
Not Only Streams for Akademia JLabsNot Only Streams for Akademia JLabs
Not Only Streams for Akademia JLabsKonrad Malawski
 
Akka and the Zen of Reactive System Design
Akka and the Zen of Reactive System DesignAkka and the Zen of Reactive System Design
Akka and the Zen of Reactive System DesignLightbend
 
ScalaSwarm 2017 Keynote: Tough this be madness yet theres method in't
ScalaSwarm 2017 Keynote: Tough this be madness yet theres method in'tScalaSwarm 2017 Keynote: Tough this be madness yet theres method in't
ScalaSwarm 2017 Keynote: Tough this be madness yet theres method in'tKonrad Malawski
 
Live coding scala 'the java of the future'
Live coding scala 'the java of the future'Live coding scala 'the java of the future'
Live coding scala 'the java of the future'Xebia Nederland BV
 
Big data beyond the JVM - DDTX 2018
Big data beyond the JVM -  DDTX 2018Big data beyond the JVM -  DDTX 2018
Big data beyond the JVM - DDTX 2018Holden Karau
 
JavaOne 2011 - JVM Bytecode for Dummies
JavaOne 2011 - JVM Bytecode for DummiesJavaOne 2011 - JVM Bytecode for Dummies
JavaOne 2011 - JVM Bytecode for DummiesCharles Nutter
 
Need for Async: Hot pursuit for scalable applications
Need for Async: Hot pursuit for scalable applicationsNeed for Async: Hot pursuit for scalable applications
Need for Async: Hot pursuit for scalable applicationsKonrad Malawski
 
JDD 2016 - Grzegorz Rozniecki - Java 8 What Could Possibly Go Wrong
JDD 2016 - Grzegorz Rozniecki - Java 8 What Could Possibly Go WrongJDD 2016 - Grzegorz Rozniecki - Java 8 What Could Possibly Go Wrong
JDD 2016 - Grzegorz Rozniecki - Java 8 What Could Possibly Go WrongPROIDEA
 
Building a Testable Data Access Layer
Building a Testable Data Access LayerBuilding a Testable Data Access Layer
Building a Testable Data Access LayerTodd Anglin
 
Beyond JVM - YOW Melbourne 2013
Beyond JVM - YOW Melbourne 2013Beyond JVM - YOW Melbourne 2013
Beyond JVM - YOW Melbourne 2013Charles Nutter
 
Debugging Spark: Scala and Python - Super Happy Fun Times @ Data Day Texas 2018
Debugging Spark:  Scala and Python - Super Happy Fun Times @ Data Day Texas 2018Debugging Spark:  Scala and Python - Super Happy Fun Times @ Data Day Texas 2018
Debugging Spark: Scala and Python - Super Happy Fun Times @ Data Day Texas 2018Holden Karau
 
Oredev 2015 - Taming Java Agents
Oredev 2015 - Taming Java AgentsOredev 2015 - Taming Java Agents
Oredev 2015 - Taming Java AgentsAnton Arhipov
 
Writing a REST Interconnection Library in Swift
Writing a REST Interconnection Library in SwiftWriting a REST Interconnection Library in Swift
Writing a REST Interconnection Library in SwiftPablo Villar
 
JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015Charles Nutter
 
Clojure: Simple By Design
Clojure: Simple By DesignClojure: Simple By Design
Clojure: Simple By DesignAll Things Open
 

Was ist angesagt? (20)

Mito, a successor of Integral
Mito, a successor of IntegralMito, a successor of Integral
Mito, a successor of Integral
 
Beyond JVM - YOW! Sydney 2013
Beyond JVM - YOW! Sydney 2013Beyond JVM - YOW! Sydney 2013
Beyond JVM - YOW! Sydney 2013
 
Down the Rabbit Hole: An Adventure in JVM Wonderland
Down the Rabbit Hole: An Adventure in JVM WonderlandDown the Rabbit Hole: An Adventure in JVM Wonderland
Down the Rabbit Hole: An Adventure in JVM Wonderland
 
Not Only Streams for Akademia JLabs
Not Only Streams for Akademia JLabsNot Only Streams for Akademia JLabs
Not Only Streams for Akademia JLabs
 
Akka and the Zen of Reactive System Design
Akka and the Zen of Reactive System DesignAkka and the Zen of Reactive System Design
Akka and the Zen of Reactive System Design
 
ScalaSwarm 2017 Keynote: Tough this be madness yet theres method in't
ScalaSwarm 2017 Keynote: Tough this be madness yet theres method in'tScalaSwarm 2017 Keynote: Tough this be madness yet theres method in't
ScalaSwarm 2017 Keynote: Tough this be madness yet theres method in't
 
Live coding scala 'the java of the future'
Live coding scala 'the java of the future'Live coding scala 'the java of the future'
Live coding scala 'the java of the future'
 
Big data beyond the JVM - DDTX 2018
Big data beyond the JVM -  DDTX 2018Big data beyond the JVM -  DDTX 2018
Big data beyond the JVM - DDTX 2018
 
JavaOne 2011 - JVM Bytecode for Dummies
JavaOne 2011 - JVM Bytecode for DummiesJavaOne 2011 - JVM Bytecode for Dummies
JavaOne 2011 - JVM Bytecode for Dummies
 
Need for Async: Hot pursuit for scalable applications
Need for Async: Hot pursuit for scalable applicationsNeed for Async: Hot pursuit for scalable applications
Need for Async: Hot pursuit for scalable applications
 
JDD 2016 - Grzegorz Rozniecki - Java 8 What Could Possibly Go Wrong
JDD 2016 - Grzegorz Rozniecki - Java 8 What Could Possibly Go WrongJDD 2016 - Grzegorz Rozniecki - Java 8 What Could Possibly Go Wrong
JDD 2016 - Grzegorz Rozniecki - Java 8 What Could Possibly Go Wrong
 
Building a Testable Data Access Layer
Building a Testable Data Access LayerBuilding a Testable Data Access Layer
Building a Testable Data Access Layer
 
Beyond JVM - YOW Melbourne 2013
Beyond JVM - YOW Melbourne 2013Beyond JVM - YOW Melbourne 2013
Beyond JVM - YOW Melbourne 2013
 
Advanced I/O in browser
Advanced I/O in browserAdvanced I/O in browser
Advanced I/O in browser
 
Debugging Spark: Scala and Python - Super Happy Fun Times @ Data Day Texas 2018
Debugging Spark:  Scala and Python - Super Happy Fun Times @ Data Day Texas 2018Debugging Spark:  Scala and Python - Super Happy Fun Times @ Data Day Texas 2018
Debugging Spark: Scala and Python - Super Happy Fun Times @ Data Day Texas 2018
 
JRuby and You
JRuby and YouJRuby and You
JRuby and You
 
Oredev 2015 - Taming Java Agents
Oredev 2015 - Taming Java AgentsOredev 2015 - Taming Java Agents
Oredev 2015 - Taming Java Agents
 
Writing a REST Interconnection Library in Swift
Writing a REST Interconnection Library in SwiftWriting a REST Interconnection Library in Swift
Writing a REST Interconnection Library in Swift
 
JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015
 
Clojure: Simple By Design
Clojure: Simple By DesignClojure: Simple By Design
Clojure: Simple By Design
 

Ähnlich wie ABRIDGED VERSION - Joys & frustrations of putting 34,000 lines of Haskell into production (at Vacation Labs)

Joys & frustrations of putting 34,000 lines of Haskell into production (at Va...
Joys & frustrations of putting 34,000 lines of Haskell into production (at Va...Joys & frustrations of putting 34,000 lines of Haskell into production (at Va...
Joys & frustrations of putting 34,000 lines of Haskell into production (at Va...Saurabh Nanda
 
XMLDB Building Blocks And Best Practices - Oracle Open World 2008 - Marco Gra...
XMLDB Building Blocks And Best Practices - Oracle Open World 2008 - Marco Gra...XMLDB Building Blocks And Best Practices - Oracle Open World 2008 - Marco Gra...
XMLDB Building Blocks And Best Practices - Oracle Open World 2008 - Marco Gra...Marco Gralike
 
Sparklife - Life In The Trenches With Spark
Sparklife - Life In The Trenches With SparkSparklife - Life In The Trenches With Spark
Sparklife - Life In The Trenches With SparkIan Pointer
 
Regex Considered Harmful: Use Rosie Pattern Language Instead
Regex Considered Harmful: Use Rosie Pattern Language InsteadRegex Considered Harmful: Use Rosie Pattern Language Instead
Regex Considered Harmful: Use Rosie Pattern Language InsteadAll Things Open
 
Scala final ppt vinay
Scala final ppt vinayScala final ppt vinay
Scala final ppt vinayViplav Jain
 
Log analysis with the elk stack
Log analysis with the elk stackLog analysis with the elk stack
Log analysis with the elk stackVikrant Chauhan
 
Weird Plsql
Weird PlsqlWeird Plsql
Weird Plsqlwebanddb
 
The Why and How of Scala at Twitter
The Why and How of Scala at TwitterThe Why and How of Scala at Twitter
The Why and How of Scala at TwitterAlex Payne
 
Ruby on Rails (RoR) as a back-end processor for Apex
Ruby on Rails (RoR) as a back-end processor for Apex Ruby on Rails (RoR) as a back-end processor for Apex
Ruby on Rails (RoR) as a back-end processor for Apex Espen Brækken
 
Null Bachaav - May 07 Attack Monitoring workshop.
Null Bachaav - May 07 Attack Monitoring workshop.Null Bachaav - May 07 Attack Monitoring workshop.
Null Bachaav - May 07 Attack Monitoring workshop.Prajal Kulkarni
 
Introduction to XtraDB Cluster
Introduction to XtraDB ClusterIntroduction to XtraDB Cluster
Introduction to XtraDB Clusteryoku0825
 
Tldr solr-courseload
Tldr solr-courseloadTldr solr-courseload
Tldr solr-courseloadmattdeboard
 
"PHP from soup to nuts" -- lab exercises
"PHP from soup to nuts" -- lab exercises"PHP from soup to nuts" -- lab exercises
"PHP from soup to nuts" -- lab exercisesrICh morrow
 
NoSQL: Why, When, and How
NoSQL: Why, When, and HowNoSQL: Why, When, and How
NoSQL: Why, When, and HowBigBlueHat
 
Scalable Web Architectures: Common Patterns and Approaches - Web 2.0 Expo NYC
Scalable Web Architectures: Common Patterns and Approaches - Web 2.0 Expo NYCScalable Web Architectures: Common Patterns and Approaches - Web 2.0 Expo NYC
Scalable Web Architectures: Common Patterns and Approaches - Web 2.0 Expo NYCCal Henderson
 
ETL with SPARK - First Spark London meetup
ETL with SPARK - First Spark London meetupETL with SPARK - First Spark London meetup
ETL with SPARK - First Spark London meetupRafal Kwasny
 

Ähnlich wie ABRIDGED VERSION - Joys & frustrations of putting 34,000 lines of Haskell into production (at Vacation Labs) (20)

Joys & frustrations of putting 34,000 lines of Haskell into production (at Va...
Joys & frustrations of putting 34,000 lines of Haskell into production (at Va...Joys & frustrations of putting 34,000 lines of Haskell into production (at Va...
Joys & frustrations of putting 34,000 lines of Haskell into production (at Va...
 
XMLDB Building Blocks And Best Practices - Oracle Open World 2008 - Marco Gra...
XMLDB Building Blocks And Best Practices - Oracle Open World 2008 - Marco Gra...XMLDB Building Blocks And Best Practices - Oracle Open World 2008 - Marco Gra...
XMLDB Building Blocks And Best Practices - Oracle Open World 2008 - Marco Gra...
 
Sparklife - Life In The Trenches With Spark
Sparklife - Life In The Trenches With SparkSparklife - Life In The Trenches With Spark
Sparklife - Life In The Trenches With Spark
 
Regex Considered Harmful: Use Rosie Pattern Language Instead
Regex Considered Harmful: Use Rosie Pattern Language InsteadRegex Considered Harmful: Use Rosie Pattern Language Instead
Regex Considered Harmful: Use Rosie Pattern Language Instead
 
Scala final ppt vinay
Scala final ppt vinayScala final ppt vinay
Scala final ppt vinay
 
Rails on Oracle 2011
Rails on Oracle 2011Rails on Oracle 2011
Rails on Oracle 2011
 
Log analysis with the elk stack
Log analysis with the elk stackLog analysis with the elk stack
Log analysis with the elk stack
 
Weird Plsql
Weird PlsqlWeird Plsql
Weird Plsql
 
The Why and How of Scala at Twitter
The Why and How of Scala at TwitterThe Why and How of Scala at Twitter
The Why and How of Scala at Twitter
 
Ruby on Rails (RoR) as a back-end processor for Apex
Ruby on Rails (RoR) as a back-end processor for Apex Ruby on Rails (RoR) as a back-end processor for Apex
Ruby on Rails (RoR) as a back-end processor for Apex
 
DSLs in JavaScript
DSLs in JavaScriptDSLs in JavaScript
DSLs in JavaScript
 
Null Bachaav - May 07 Attack Monitoring workshop.
Null Bachaav - May 07 Attack Monitoring workshop.Null Bachaav - May 07 Attack Monitoring workshop.
Null Bachaav - May 07 Attack Monitoring workshop.
 
Introduction to XtraDB Cluster
Introduction to XtraDB ClusterIntroduction to XtraDB Cluster
Introduction to XtraDB Cluster
 
Tldr solr-courseload
Tldr solr-courseloadTldr solr-courseload
Tldr solr-courseload
 
"PHP from soup to nuts" -- lab exercises
"PHP from soup to nuts" -- lab exercises"PHP from soup to nuts" -- lab exercises
"PHP from soup to nuts" -- lab exercises
 
NoSQL: Why, When, and How
NoSQL: Why, When, and HowNoSQL: Why, When, and How
NoSQL: Why, When, and How
 
A Practical Multi-Tenant Cluster
A Practical Multi-Tenant ClusterA Practical Multi-Tenant Cluster
A Practical Multi-Tenant Cluster
 
Not only SQL
Not only SQL Not only SQL
Not only SQL
 
Scalable Web Architectures: Common Patterns and Approaches - Web 2.0 Expo NYC
Scalable Web Architectures: Common Patterns and Approaches - Web 2.0 Expo NYCScalable Web Architectures: Common Patterns and Approaches - Web 2.0 Expo NYC
Scalable Web Architectures: Common Patterns and Approaches - Web 2.0 Expo NYC
 
ETL with SPARK - First Spark London meetup
ETL with SPARK - First Spark London meetupETL with SPARK - First Spark London meetup
ETL with SPARK - First Spark London meetup
 

Kürzlich hochgeladen

2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 

Kürzlich hochgeladen (20)

2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 

ABRIDGED VERSION - Joys & frustrations of putting 34,000 lines of Haskell into production (at Vacation Labs)

  • 1. Joys & frustrations of putting 34,000 lines of Haskell into production NOTE: Another version of these slides (with more text) is available at https://www.slideshare.net/saurabhnanda/joys-frustrations-of-putting-34000-lines- of-haskell-into-production-at-vacation-labs Haskell
  • 2. Source of all this gyaan 34,000 LoC of Haskell in production Touched (almost) all aspects of a typical web-app stack Except Haskell (or Purescript) in the frontend. Using Angular2 + TypeScript instead.
  • 3.
  • 4. Why Haskell?Why Haskell? आ बैल मुझे मारआ बैल मुझे मार
  • 5. Vacation Labs Travel-Commerce Platform Enabling travel companies with e-commerce technology. Built mostly with Rails & Angular-v1 (Javascript)
  • 6. Remember those numbers “It's always good to remember where you come from and celebrate it. To remember where you come from is part of where you're going.” - Anthony Burgess
  • 7. Problems with Rails/JS Code Unable to refactor core data-structures confidently Unable to remove dead-code without fear of breaking Unable to review code effectively
  • 8.
  • 9.
  • 10.
  • 11. Building webapps in Haskell is harder than it ought to be What I felt a year ago, just starting out... http://tinyurl.com/haskell-is-needlessly-hard
  • 14. { “Type-safe” : “JSON” } Aeson is brilliant. Auto-derives a lot of boilerplate. OTOH writing JSON codecs in TypeScript by hand.
  • 15. HTTP / Web / App Server WAI/Warp has pretty good performance. One lightweight thread per-incoming request. Solid concurrency without an event-driven / callback model (unlike node).
  • 17. Big problems faced first-hand Library eco-system is effectively broken Lack of established best-practices Editor tooling Records Lack of ORM
  • 18. Library ecosystem is effectively broken Lack of libraries it NOT a problem Fragmentation, non-standardization Heaps of cruft on Hackage Broken library ecosystem
  • 19. I can easily compare Haskell libraries to select the best one Strongly disagree Disagree Neutral Agree Strongly agree 100 200 300 400 500
  • 20. I can easily compare Haskell libraries to select the best one Strongly disagree Disagree Neutral Agree Strongly agree 100 200 300 400 500 44% respondents replied negatively
  • 21. Emails SES, Postmark, Mandrill, raw SMTP, etc. All there. Fiasco with `smtp-mail` library. Broken library ecosystem
  • 22. Sendgrid library `haskell-sendgrid` is incomplete. We wrote our own. Ping us on Twitter if you want to help open-source our code. (Open bounty) http://www.vacationlabs.com/haskell-bounty-program/ Call for contribution
  • 23. Testing 287 packages related to testing None of them runs tests in isolated DB txns out-of-the-box. Broken library ecosystem
  • 24. DB libraries persistent, hedgehog, hasql, pg-simple, opaleye, mysql-simple, HaskellDB Which to use when? Why so many? Broken library ecosystem
  • 25. Lack of established best-practices Community keeps arguing about core stuff stack vs cabal mtl vs free-monads error handling Is TH good or bad? No best practices
  • 26. Installing Haskell FOUR different ways to install Haskell - seriously?! PS: Just use “stack” - tried & tested. LTS snapshots are awesome! No best practices
  • 27.
  • 28. Error handling EIGHT different ways. Each library uses something else. http://www.randomhacks.net/2007/03/10/haskell-8-ways-to-report-errors/ `ExceptT` vs `Conrol.Monad.Catch` fiasco No best practices
  • 29. do x <- runExceptT (liftIO $ throwIO DivideByZero) case x of Left e -> pure “exception caught” Right r -> pure “should never happen!”
  • 30. do x <- runExceptT (liftIO $ throwIO DivideByZero) case x of Left e -> pure “exception caught” Right r -> pure “should never happen!” -- OUTPUT *** Exception: divide by zero -- Reaction: Wtf ?!
  • 31. do x <- Control.Monad.Catch.try (liftIO $ throwIO DivideByZero) case x of Left (e :: SomeException) -> pure “exception caught” Right r -> pure “should never happen!”
  • 32. do x <- Control.Monad.Catch.try (liftIO $ throwIO DivideByZero) case x of Left (e :: SomeException) -> pure “exception caught” Right r -> pure “should never happen!” -- OUTPUT “exception caught”
  • 33. Error reporting Haskell code throws runtime errors. Please report them properly. Hype - “if it compiles, it runs”. Reality - “after a refactor, if it compiles, then there is a high chance that you haven’t broken anything” No best practices
  • 34.
  • 35. Which file? Turns out “fastLogger” was trying to open a log-file in a non-existent directory. (On LTS-9.0)
  • 36. *** Exception: UnexpectedNull { errSQLType = “varchar” , errSQLTableOid = Just (Oid 603560) , errSQLField = “result22_2” , errHaskellType = “Text” , errMessage = “” }
  • 37. *** Exception: UnexpectedNull { errSQLType = “varchar” , errSQLTableOid = Just (Oid 603560) , errSQLField = “result22_2” , errHaskellType = “Text” , errMessage = “” } Which row? What SQL was being run? Any other info that can help me debug this? Stacktrace?
  • 38.
  • 39. Occurred during stress testing of JSON API. Wasted a lot of time! Which file descriptor? Which library was accessing it? Nothing! Turned out that DB pool size was larger than what DB could handle.
  • 40. Absence of CallStacks can probably be fixed Call for contribution Imperceptible perf-penalty with HasCallStack in IO code Not being used by IO-heavy libraries. Raise some PRs! GHC discussion to infer HasCallStack automatically https://ghc.haskell.org/trac/ghc/ticket/13360
  • 41. Testing We drank the QuickCheck kool-aid QuickCheck fiasco No best practices
  • 42. Editor tooling SAD TRUTH - Nothing works as well as it should. Tried a lot of things Emacs + haskell-mode, Spacemacs + Intero, SublimeHaskell, Haskero, Haskelly, HIE, ghcid, etc. Underlying GHCi hogs/leaks memory. Editor tooling
  • 43.
  • 44. Important caveat about memory usage Haskell DOES NOT leak memory in production. Only present in GHC-i -- used in development. Production Rails-app: 360 MB of RSS (x 3 processes) Production Haskell-app: 78 MB of RSS (single process).
  • 45. Recommendation: Editor tooling Use spacemacs + intero OR VSCode + HIE (Haskell IDE Engine) Keep ghci open in a terminal window and make friends with :set -fobject-code & :load & :reload
  • 46. Shout-out to HIE (Haskell IDE Engine) Call for contribution Please use it, if it works for you. Make it work for you! Contribute if you can. https://github.com/haskell/haskell-ide-engine
  • 47. Broken record Records. Records. Records. Records in Haskell are beyond horrible. Some say, Haskell doesn’t even have records. http://www.parsonsmatt.org/overcoming-records/
  • 48. -- Your `users` table would probably map to the following… data User = User { userId :: UserId , userCreatedAt :: UTCTime , userUpdatedAt :: UTCTime, , userStatus :: UserStatus, , userName :: Maybe Text , userEmail :: Text , userAge :: Maybe Int } -- But, you can’t use this in your `createUser` endpoint. -- UI shouldn’t set `id, createdAt, updatedAt, status` -- No easy way to create a “sub-record” from a master record.
  • 49. -- Created our own library `record-splicer` to deal with this... createRecordSplice SpliceArgs { sourcePrefix = "user" , source = ''User , requiredFields = [ 'userName , 'userEmail , 'userAge ] , targetPrefix = "newuser" , targetName = "NewUser" , deriveClasses = [''Eq, ''Show, ''Generic] } makeLensesWith abbreviatedFields ''NewUser
  • 50. // Same thing in TypeScript type interface User { readonly id: number , readonly createdAt: DateTime , readonly updatedAt: DateTime , readonly status: ‘unconfirmed’ | ‘confirmed’ | ‘blocked’ , readonly name: string | null , readonly email: string , readonly age: string | null } // Making a typesafe sub-record type NewUser = Pick <User, ‘name’ | ‘email’ | ‘age’>; // Making a typesafe super-record type Admin extends User { readonly permissions: Array<Permission> }
  • 51. DB Library. Dare I say ORM? Either you use an ORM or you write an ad-hoc ORM. Tried to understand how to build apps without an ORM. Not convinced. At all. [1] [2] [3] [4] Lack of ORM
  • 52. Associations? No DB library deals with associations. Except two new discoveries - beam & postgresql-orm Lack of ORM
  • 53. Validations? No DB library deals with validations. Rails’ convention of putting strict invariants/validations in the DB layer works ridiculously well. Lack of ORM
  • 54. Validations in DB-layer are an anti-pattern? Let’s look state-of-the-art: “digestive-functors” Lack of ORM
  • 55.
  • 56. DB Library Problem as well. Incomplete / half-baked DB libraries mysql-simple - (had?) concurrency issues postgresql-simple doesn’t use PREPARE/EXECUTE Opaleye generates slow queries Lack of ORM
  • 57. Applicative parsers? Or “Hodor” parsers. Special hate for applicative parsers! Negate all benefits of static typing. Especially true for postgresql-simple. Lack of ORM
  • 58. query_ = ([qc| SELECT c.id as client_id , coalesce(c.custom_domain, c.domain) as domain , c.home_page as home_page , c.support_phone as support_phone , c.support_email as support_email , c.logo_photo_id as loto_photo_id , logo_photo.image_file_name as logo_file_name , logo_photo.image_fingerprint as logo_fingerprint , c.favicon_image_id as favicon_image_id , favicon.image_file_name as favicon_file_name …
  • 59. query_ = ([qc| SELECT c.id as client_id , coalesce(c.custom_domain, c.domain) as domain , c.home_page as home_page , c.support_phone as support_phone , c.support_email as support_email , c.logo_photo_id as loto_photo_id , logo_photo.image_file_name as logo_file_name , logo_photo.image_fingerprint as logo_fingerprint , c.favicon_image_id as favicon_image_id , favicon.image_file_name as favicon_file_name … rowParser assetHost_ = Storefront <$> field <*> field <*> field <*> field <*> field <*> (photoEssentialsParser assetHost_ Photo.WebsiteLogo) <*> (photoEssentialsParser assetHost_ Photo.Favicon) <*> field <*> field <*> field <*> field <*> field <*> field <*> field <*> field <*> field <*> field <*> field <*> field <*> field <*> field <*> hstoreBoolParser <*> field <*> field <*> field <*> field <*> field <*> field <*> field
  • 60. query_ = ([qc| SELECT c.id as hodor , coalesce(c.custom_domain, c.domain) as hodor , c.home_page as hodor , c.support_phone as hodor , c.support_email as hodor , c.logo_photo_id as hodor , logo_photo.image_file_name as hodor , logo_photo.image_fingerprint as hodor , c.favicon_image_id as hodor , favicon.image_file_name as hodor … rowParser assetHost_ = Storefront <$> hodor <*> hodor <*> hodor <*> hodor <*> hodor <*> (photoEssentialsParser assetHost_ Photo.WebsiteLogo) <*> (photoEssentialsParser assetHost_ Photo.Favicon) <*> hodor <*> hodor <*> hodor <*> hodor <*> hodor <*> hodor <*> hodor <*> hodor <*> hodor <*> hodor <*> hodor <*> hodor <*> hodor <*> hodor <*> hstoreBoolParser <*> hodor <*> hodor <*> hodor <*> hodor <*> hodor <*> hodor <*> hodor
  • 61. PG-Simple’s “hodor” parser can be fixed There is an open bounty. https://github.com/lpsmith/postgresql-simple/issues/43 http://www.vacationlabs.com/haskell-bounty-program Call for contribution
  • 62. What did we really build in 38,000 lines of Haskell? Flexi-payment plugin DelayedJob clone (but using LISTEN/NOTIFY) along with UI Sendgrid library Opaleye boilerplate code-generator Deep instrumentation wrappers over core libs
  • 63.
  • 64. Logging & Instrumentation “Deep instrumentation” in Haskell seems to be non-existent Eg. kind of stuff provided by Rails out of box, or Skylight, or New Relic Very hard to build drop-in instrumentation libraries for Haskell. Probably because of the type-system itself. http://tinyurl.com/haskell-instrumentation Built our own ad-hoc logging & instrumentation layer by wrapping important libs
  • 65. Job Queue Rails has DelayedJob (with an RDBMS backend). Works really well for moderate workloads. ACID compliant and doesn’t add more moving parts to production. Couldn’t find anything similar in Haskell world. Built our own. Will open-source. Except `yesod-job-queue` but we aren’t using Yesod. Redis & SQS job-queues available, but we didn’t use first-hand. Can’t comment.
  • 66. JobAdmin UI built by intern in 4 months (included learning Haskell). Built using Servant, Lucid, Aeson, Opaleye.
  • 67. Initial (excruciating) pain for long-term gain We have already gone through the pain Now, we are reaping the gains Haskell sucks. Why continue with it?
  • 68. What’s next? Raising awareness about the issues we faced. The core language is not as confusing as the ecosystem is. Contributing in any way to fix the ecosystem.
  • 69. Thank you @saurabhnanda on twitter @vacationlabs on instagram Haskell Bounty Program Haskell Internship Program We’re hiring Haskellers (and Haskell enthusiasts)