Functional Database Strategies at Scala Bay

111
Functional Database Strategies Scala Bay • March 20, 2017

Transcript of Functional Database Strategies at Scala Bay

Page 1: Functional Database Strategies at Scala Bay

Functional Database Strategies

Scala Bay • March 20, 2017

Page 2: Functional Database Strategies at Scala Bay

HelloScala Bay

HelloScala Bay

Page 3: Functional Database Strategies at Scala Bay

YesQL

Page 4: Functional Database Strategies at Scala Bay

by Jason Swartz@swartzrock

Page 5: Functional Database Strategies at Scala Bay
Page 6: Functional Database Strategies at Scala Bay

Functional Database Strategies

Page 7: Functional Database Strategies at Scala Bay

Step One

Buy A Functional Database

Page 8: Functional Database Strategies at Scala Bay

Silly! Databases Aremutable, not

functional!

Page 9: Functional Database Strategies at Scala Bay

Well?Aren’t they?

Page 10: Functional Database Strategies at Scala Bay

1. Functional DB’s In Scalaa. Doobie

2. Functional DB’s In The Databasea. Immutable Rowsb. Window Functionsc. Events, Not State

Agenda

Page 11: Functional Database Strategies at Scala Bay

1. Functional DB’s In Scalaa. Doobie

2. Functional DB’s In The Databasea. Immutable Rowsb. Window Functionsc. Events, Not State

Agenda

Page 12: Functional Database Strategies at Scala Bay

1. Functional DB’s In Scalaa. Doobie

2. Functional DB’s In The Databasea. Immutable Rowsb. Window Functionsc. Events, Not State

Agenda

Page 13: Functional Database Strategies at Scala Bay

Remember That YourDatabase

is mutable.

Page 14: Functional Database Strategies at Scala Bay

Avoid SharingYour State

Page 15: Functional Database Strategies at Scala Bay

● Avoid shared mutable SESSIONS ● Avoid shared mutable CURSORS ● Mutating state? Cool! But MODEL IT FIRST● Execute state changes at THE EDGE

Safe Database Interactions

Page 16: Functional Database Strategies at Scala Bay

DoobieA Typelevel Project

Page 17: Functional Database Strategies at Scala Bay

Are these steps? Or a Monad?

Page 18: Functional Database Strategies at Scala Bay

val xa: Transactor[Task] = DriverManagerTransactor[Task]( "org.postgresql.Driver", "jdbc:postgresql://localhost/issues", "u", "p")

Page 19: Functional Database Strategies at Scala Bay

case class Issue(id: Int, issueId: Int, title: String, assignee: Int, status: String)

val issue: Issue = sql""" select id, issue_id, title, assignee, status from issues where issue_id = ${req.issue_id} order by id desc limit 1 """ .query[Issue] .unique .transact(xa) .unsafePerformSync

Page 20: Functional Database Strategies at Scala Bay

● ResultSet to Case Class Conversion● Async IO modeling with Task (scalaz version)● Think in SQL, not an ORM● Plain SQL with sql"" interpolation● SQL functions supported

Why Doobie?

Page 21: Functional Database Strategies at Scala Bay

1. Functional DB’s In Scalaa. Doobie

2. Functional DB’s In The Databasea. Immutable Rowsb. Window Functionsc. Events, Not State

Agenda

Page 22: Functional Database Strategies at Scala Bay

1. Functional DB’s In Scalaa. Doobie

2. Functional DB’s In The Databasea. Immutable Rowsb. Window Functionsc. Events, Not State

Agenda

Page 23: Functional Database Strategies at Scala Bay

Let’s Talk AboutImmutable Tables

Page 24: Functional Database Strategies at Scala Bay
Page 25: Functional Database Strategies at Scala Bay
Page 26: Functional Database Strategies at Scala Bay

Create-Read-Update-Delete

Page 27: Functional Database Strategies at Scala Bay

GET /issuesGET /issues/{id}POST /issuesPUT /issues/{id}

Issue Endpoints

Page 28: Functional Database Strategies at Scala Bay

How Do These EventsAffect The Database?

Page 29: Functional Database Strategies at Scala Bay

1. POST /issues title=’Config ELB’

+------+-------------+------------+----------+-------+| id | updated | title | assignee | done |+------+-------------+------------+----------+-------+| 1 | 09-18 18:13 | Config ELB | NULL | false |+------+-------------+------------+----------+-------+

Page 30: Functional Database Strategies at Scala Bay

1. POST /issues title=’Config ELB’2. PUT /issues/1 assignee=10

+------+-------------+------------+----------+-------+| id | updated | title | assignee | done |+------+-------------+------------+----------+-------+| 1 | 09-18 18:16 | Config ELB | 10 | false |+------+-------------+------------+----------+-------+

Page 31: Functional Database Strategies at Scala Bay

1. POST /issues title=’Config ELB’2. PUT /issues/1 assignee=103. PUT /issues/1 done=true

+------+-------------+------------+----------+-------+| id | updated | title | assignee | done |+------+-------------+------------+----------+-------+| 1 | 09-18 18:24 | Config ELB | NULL | true |+------+-------------+------------+----------+-------+

Page 32: Functional Database Strategies at Scala Bay

1. POST /issues title=’Config ELB’2. PUT /issues/1 assignee=103. PUT /issues/1 done=true

+------+-------------+------------+----------+-------+| id | updated | title | assignee | done |+------+-------------+------------+----------+-------+| 1 | 09-18 18:24 | Config ELB | NULL | true |+------+-------------+------------+----------+-------+

Not Bad.

Page 33: Functional Database Strategies at Scala Bay

1. POST /issues title=’Config ELB’2. PUT /issues/1 assignee=103. PUT /issues/1 done=true

+------+-------------+------------+----------+-------+| id | updated | title | assignee | done |+------+-------------+------------+----------+-------+| 1 | 09-18 18:24 | Config ELB | NULL | true |+------+-------------+------------+----------+-------+

Do You Know How We Got Here?

Page 34: Functional Database Strategies at Scala Bay

+------+-------------+------------+----------+-------+| id | updated | title | assignee | done |+------+-------------+------------+----------+-------+| 1 | 09-18 18:24 | Config ELB | NULL | true |+------+-------------+------------+----------+-------+

Do You Know How We Got Here?

Page 35: Functional Database Strategies at Scala Bay

1. POST /issues title=’Config ELB’2. PUT /issues/1 assignee=103. PUT /issues/1 done=true

+------+-------------+------------+----------+-------+| id | updated | title | assignee | done |+------+-------------+------------+----------+-------+| 1 | 09-18 18:24 | Config ELB | NULL | true |+------+-------------+------------+----------+-------+

Do You Know How We Got Here?

Page 36: Functional Database Strategies at Scala Bay

1. POST /issues title=’Config ELB’2. PUT /issues/1 assignee=103. PUT /issues/1 done=true

+------+-------------+------------+----------+-------+| id | updated | title | assignee | done |+------+-------------+------------+----------+-------+| 1 | 09-18 18:24 | Config ELB | NULL | true |+------+-------------+------------+----------+-------+

Why is ‘assignee’ NULL?

Page 37: Functional Database Strategies at Scala Bay

Mutable Table Rows Lose History

Page 38: Functional Database Strategies at Scala Bay

Immutable Table Rows Keep Their History

Page 39: Functional Database Strategies at Scala Bay

Let’s Try To Lock Down

Our State

Page 40: Functional Database Strategies at Scala Bay

1. POST /issues title=’Config ELB’

+------+-------------+------------+----------+-------+| id | updated | title | assignee | done |+------+-------------+------------+----------+-------+| 1 | 09-18 18:13 | Config ELB | NULL | false |+------+-------------+------------+----------+-------+

Page 41: Functional Database Strategies at Scala Bay

1. POST /issues title=’Config ELB’2. PUT /issues/1 assignee=10

+------+-------------+------------+----------+-------+| id | updated | title | assignee | done |+------+-------------+------------+----------+-------+| 1 | 09-18 18:13 | Config ELB | NULL | false |+------+-------------+------------+----------+-------+| 1 | 09-18 18:16 | Config ELB | 10 | false |+------+-------------+------------+----------+-------+

Page 42: Functional Database Strategies at Scala Bay

1. POST /issues title=’Config ELB’2. PUT /issues/1 assignee=103. PUT /issues/1 done=true

+------+-------------+------------+----------+-------+| id | updated | title | assignee | done |+------+-------------+------------+----------+-------+| 1 | 09-18 18:13 | Config ELB | NULL | false |+------+-------------+------------+----------+-------+| 1 | 09-18 18:16 | Config ELB | 10 | false |+------+-------------+------------+----------+-------+| 1 | 09-18 18:19 | Config ELB | NULL | false |+------+-------------+------------+----------+-------+| 1 | 09-18 18:24 | Config ELB | NULL | true |+------+-------------+------------+----------+-------+

Page 43: Functional Database Strategies at Scala Bay

1. POST /issues title=’Config ELB’2. PUT /issues/1 assignee=103. PUT /issues/1 done=true

+------+-------------+------------+----------+-------+| id | updated | title | assignee | done |+------+-------------+------------+----------+-------+| 1 | 09-18 18:13 | Config ELB | NULL | false |+------+-------------+------------+----------+-------+| 1 | 09-18 18:16 | Config ELB | 10 | false |+------+-------------+------------+----------+-------+| 1 | 09-18 18:19 | Config ELB | NULL | false |+------+-------------+------------+----------+-------+| 1 | 09-18 18:24 | Config ELB | NULL | true |+------+-------------+------------+----------+-------+

Page 44: Functional Database Strategies at Scala Bay

1. GET /issues/1

+------+-------------+------------+----------+-------+| id | updated | title | assignee | done |+------+-------------+------------+----------+-------+| 1 | 09-18 18:13 | Config ELB | NULL | false |+------+-------------+------------+----------+-------+| 1 | 09-18 18:16 | Config ELB | 10 | false |+------+-------------+------------+----------+-------+| 1 | 09-18 18:19 | Config ELB | NULL | false |+------+-------------+------------+----------+-------+

+------+-------------+------------+----------+-------+| 1 | 09-18 18:24 | Config ELB | NULL | true |+------+-------------+------------+----------+-------+

Page 45: Functional Database Strategies at Scala Bay

Tables Are Mutable, But Table Rows Should Be

Immutable

Page 46: Functional Database Strategies at Scala Bay

In Other Words, Tables Should Be

Append-Only

Page 47: Functional Database Strategies at Scala Bay

How Do You Make An Append-Only

Table?

Page 48: Functional Database Strategies at Scala Bay

One: Don’t Let Your DB User Make

Changes

Page 49: Functional Database Strategies at Scala Bay

Grant select, insert on issues to my-db-user;

-- tested on Postgresql

Page 50: Functional Database Strategies at Scala Bay

Thank You! Goodbye!

Page 51: Functional Database Strategies at Scala Bay

Two: Pick The RightColumns

Page 52: Functional Database Strategies at Scala Bay

1. GET /issues/1

+------+-------------+------------+----------+-------+| id | updated | title | assignee | done |+------+-------------+------------+----------+-------+| 1 | 09-18 18:13 | Config ELB | NULL | false |+------+-------------+------------+----------+-------+| 1 | 09-18 18:16 | Config ELB | 10 | false |+------+-------------+------------+----------+-------+| 1 | 09-18 18:19 | Config ELB | NULL | false |+------+-------------+------------+----------+-------+

+------+-------------+------------+----------+-------+| 1 | 09-18 18:24 | Config ELB | NULL | true |+------+-------------+------------+----------+-------+

Page 53: Functional Database Strategies at Scala Bay

create table issues ( id serial, created timestamp default now(), issue_id int default nextval(‘iseq’), title text, assignee int, done boolean default false)

Page 54: Functional Database Strategies at Scala Bay

1. GET /issues/1

+------+-------------+------------+------------+----------+-------+| id | created | issue_id | title | assignee | done |+------+-------------+------------+------------+----------+-------+| 1 | 09-18 18:13 | 1 | Config ELB | NULL | false |+------+-------------+------------+------------+----------+-------+| 2 | 09-18 18:16 | 1 | Config ELB | 10 | false |+------+-------------+------------+------------+----------+-------+| 3 | 09-18 18:19 | 1 | Config ELB | NULL | false |+------+-------------+------------+------------+----------+-------+

+------+-------------+------------+------------+----------+-------+| 4 | 09-18 18:24 | 1 | Config ELB | NULL | true |+------+-------------+------------+------------+----------+-------+

Page 55: Functional Database Strategies at Scala Bay

select * from issueswhere issue_id = :issue_idorder by id desc limit 1;

Page 56: Functional Database Strategies at Scala Bay

What Defines AnIssue,

The Version or the Entity?

Page 57: Functional Database Strategies at Scala Bay

ISSUES+------+-------------+------------+------------+----------+-------+| id | created | issue_id | title | assignee | done |+------+-------------+------------+------------+----------+-------+| 1 | 09-18 18:13 | 1 | Config ELB | NULL | false |+------+-------------+------------+------------+----------+-------+| 2 | 09-18 18:16 | 1 | Config ELB | 10 | false |+------+-------------+------------+------------+----------+-------+| 3 | 09-18 18:19 | 1 | Config ELB | NULL | false |+------+-------------+------------+------------+----------+-------+

Page 58: Functional Database Strategies at Scala Bay

create table issues ( id serial, created timestamp default now(), issue_id int default nextval(‘iseq’), title text, assignee int, done boolean default false )

create table notifications ( id serial, created timestamp default now(), issue_row_id int references issues )

Page 59: Functional Database Strategies at Scala Bay

ISSUES+------+-------------+------------+------------+----------+-------+| id | created | issue_id | title | assignee | done |+------+-------------+------------+------------+----------+-------+| 1 | 09-18 18:13 | 1 | Config ELB | NULL | false |+------+-------------+------------+------------+----------+-------+| 2 | 09-18 18:16 | 1 | Config ELB | 10 | false |+------+-------------+------------+------------+----------+-------+| 3 | 09-18 18:19 | 1 | Config ELB | NULL | false |+------+-------------+------------+------------+----------+-------+

NOTIFICATIONS+------+-------------+--------------+| id | created | issue_row_id | +------+-------------+--------------+| 1 | 09-18 19:13 | 2 |+------+-------------+--------------+

Page 60: Functional Database Strategies at Scala Bay

ISSUES+------+-------------+------------+------------+----------+-------+| id | created | issue_id | title | assignee | done |+------+-------------+------------+------------+----------+-------+| 1 | 09-18 18:13 | 1 | Config ELB | NULL | false |+------+-------------+------------+------------+----------+-------+| 2 | 09-18 18:16 | 1 | Config ELB | 10 | false |+------+-------------+------------+------------+----------+-------+| 3 | 09-18 18:19 | 1 | Config ELB | NULL | false |+------+-------------+------------+------------+----------+-------+

NOTIFICATIONS+------+-------------+--------------+| id | created | issue_row_id | +------+-------------+--------------+| 1 | 09-18 19:13 | 2 |+------+-------------+--------------+

Page 61: Functional Database Strategies at Scala Bay

Issue Notifications AreImmutableIn The Database

Page 62: Functional Database Strategies at Scala Bay

That’s The Basics Of Immutability

In Table Rows

Page 63: Functional Database Strategies at Scala Bay

1. Functional DB’s In Scalaa. Doobie

2. Functional DB’s In The Databasea. Immutable Rowsb. Window Functionsc. Events, Not State

Agenda

Page 64: Functional Database Strategies at Scala Bay

1. Functional DB’s In Scalaa. Doobie

2. Functional DB’s In The Databasea. Immutable Rowsb. Window Functionsc. Events, Not State

Agenda

Page 65: Functional Database Strategies at Scala Bay

SQL:2003 expands Groups into Windows

Page 66: Functional Database Strategies at Scala Bay

Works Great InPostgresql

Page 67: Functional Database Strategies at Scala Bay

● Aggregation functions, eg sum(), rank(), avg()● Window definitions with over()● Grouping with partition by, order

Window Functions

Page 68: Functional Database Strategies at Scala Bay

+------+------------+------------+----------+-------+| id | issue_id | title | assignee | done |+------+------------+------------+----------+-------+| 1 | 1 | Config ELB | NULL | false |+------+------------+------------+----------+-------+| 2 | 1 | Config ELB | 10 | false |+------+------------+------------+----------+-------+| 3 | 2 | Bug to fix | 11 | false |+------+------------+------------+----------+-------+| 4 | 2 | Bug to fix | 11 | true |+------+------------+------------+----------+-------+

Page 69: Functional Database Strategies at Scala Bay

+------+------------+------------+----------+-------+| id | issue_id | title | assignee | done |+------+------------+------------+----------+-------+| 1 | 1 | Config ELB | NULL | false |+------+------------+------------+----------+-------+| 2 | 1 | Config ELB | 10 | false |+------+------------+------------+----------+-------+| 3 | 2 | Bug to fix | 11 | false |+------+------------+------------+----------+-------+| 4 | 2 | Bug to fix | 11 | true |+------+------------+------------+----------+-------+

Page 70: Functional Database Strategies at Scala Bay

with latest_issues as ( select *, row_number() over ( partition by issue_id order by id desc ) from issues where created > now() - interval '7 day')select * from latest_issues where row_number = 1

Page 71: Functional Database Strategies at Scala Bay

with latest_issues as ( select *, row_number() over ( partition by issue_id order by id desc ) from issues where created > now() - interval '7 day')select * from latest_issues where row_number = 1

Page 72: Functional Database Strategies at Scala Bay

with latest_issues as ( select *, row_number() over ( partition by issue_id order by id desc ) from issues where created > now() - interval '7 day')select * from latest_issues where row_number = 1

Page 73: Functional Database Strategies at Scala Bay

with latest_issues as ( select *, row_number() over ( partition by issue_id order by id desc ) from issues where created > now() - interval '7 day')select * from latest_issues where row_number = 1

Page 74: Functional Database Strategies at Scala Bay

+------+------------+------------+----------+-------+------------+| id | issue_id | title | assignee | done | row_number |+------+------------+------------+----------+-------+------------+| 1 | 1 | Config ELB | NULL | false | 2 |+------+------------+------------+----------+-------+------------+| 2 | 1 | Config ELB | 10 | false | 1 |+------+------------+------------+----------+-------+------------+| 3 | 2 | Bug to fix | 11 | false | 2 |+------+------------+------------+----------+-------+------------+| 4 | 2 | Bug to fix | 11 | true | 1 |+------+------------+------------+----------+-------+------------+

Page 75: Functional Database Strategies at Scala Bay

+------+------------+------------+----------+-------+------------+| id | issue_id | title | assignee | done | row_number |+------+------------+------------+----------+-------+------------+| 1 | 1 | Config ELB | NULL | false | 2 |+------+------------+------------+----------+-------+------------+| 2 | 1 | Config ELB | 10 | false | 1 |+------+------------+------------+----------+-------+------------+| 3 | 2 | Bug to fix | 11 | false | 2 |+------+------------+------------+----------+-------+------------+| 4 | 2 | Bug to fix | 11 | true | 1 |+------+------------+------------+----------+-------+------------+

Page 76: Functional Database Strategies at Scala Bay

+------+------------+------------+----------+-------+------------+| id | issue_id | title | assignee | done | row_number |+------+------------+------------+----------+-------+------------+| 1 | 1 | Config ELB | NULL | false | 2 |+------+------------+------------+----------+-------+------------+| 2 | 1 | Config ELB | 10 | false | 1 |+------+------------+------------+----------+-------+------------+| 3 | 2 | Bug to fix | 11 | false | 2 |+------+------------+------------+----------+-------+------------+| 4 | 2 | Bug to fix | 11 | true | 1 |+------+------------+------------+----------+-------+------------+

Page 77: Functional Database Strategies at Scala Bay

That WasWindow

Functions

Page 78: Functional Database Strategies at Scala Bay

1. Functional DB’s In Scalaa. Doobie

2. Functional DB’s In The Databasea. Immutable Rowsb. Window Functionsc. Events, Not State

Agenda

Page 79: Functional Database Strategies at Scala Bay

1. Functional DB’s In Scalaa. Doobie

2. Functional DB’s In The Databasea. Immutable Rowsb. Window Functionsc. Events, Not State

Agenda

Page 80: Functional Database Strategies at Scala Bay

You Know How To Maintain State

Page 81: Functional Database Strategies at Scala Bay

Do We Still Need State?

Page 82: Functional Database Strategies at Scala Bay

Let’s Talk AboutEvent-Sourcing

Page 83: Functional Database Strategies at Scala Bay

1. POST /issues title=’Config ELB’2. PUT /issues/1 assignee=103. PUT /issues/1 done=true

+------+-------------+------------+----------+-------+| id | updated | title | assignee | done |+------+-------------+------------+----------+-------+| 1 | 09-18 18:13 | Config ELB | NULL | false |+------+-------------+------------+----------+-------+| 1 | 09-18 18:16 | Config ELB | 10 | false |+------+-------------+------------+----------+-------+| 1 | 09-18 18:24 | Config ELB | 10 | true |+------+-------------+------------+----------+-------+

Page 84: Functional Database Strategies at Scala Bay

1. POST /issues title=’Config ELB’2. PUT /issues/1 assignee=103. PUT /issues/1 done=true

+------+-------------+------------+----------+-------+| id | updated | title | assignee | done |+------+-------------+------------+----------+-------+| 1 | 09-18 18:13 | Config ELB | NULL | false |+------+-------------+------------+----------+-------+| 1 | 09-18 18:16 | Config ELB | 10 | false |+------+-------------+------------+----------+-------+| 1 | 09-18 18:24 | Config ELB | 10 | true |+------+-------------+------------+----------+-------+

Events

States

Page 85: Functional Database Strategies at Scala Bay
Page 86: Functional Database Strategies at Scala Bay
Page 87: Functional Database Strategies at Scala Bay
Page 88: Functional Database Strategies at Scala Bay
Page 89: Functional Database Strategies at Scala Bay

Now We’re Storing Events,

Not States

Page 90: Functional Database Strategies at Scala Bay

create table issue_events ( id serial, created timestamp default now(), issue_id int default nextval(‘iseq’), originator text, payload text)

Page 91: Functional Database Strategies at Scala Bay

1. POST /issue/1/event ‘Originator: 4a48239-8a..’ payload=’<Update val=”done=true”>’

+----+-------------+----------+------------+---------+| id | created | issue_id | originator | payload |+----+-------------+----------+------------+---------+| 14 | 09-18 18:50 | 1 | 4a482... | <...> |+----+-------------+----------+------------+---------+

Page 92: Functional Database Strategies at Scala Bay

Create Events AndSimulate The State

Page 93: Functional Database Strategies at Scala Bay

1. Create-Issue

Issue(“Config ELB”, null, false);

Real Events

Virtual States

Page 94: Functional Database Strategies at Scala Bay

1. Create-Issue2. Assign-Issue

Issue(“Config ELB”, 10, false);

Real Events

Virtual States

Page 95: Functional Database Strategies at Scala Bay

1. Create-Issue2. Assign-Issue3. Complete-Issue

Issue(“Config ELB”, 10, true);

Real Events

Virtual States

Page 96: Functional Database Strategies at Scala Bay

So Why UseEvent-Sourcing?

Page 97: Functional Database Strategies at Scala Bay

1. High Write Performance2. Potential for Command/Query Separation3. Auditable4. Replayable5. Undo-able6. Monitorable

Reasons For Event-Sourcing

Page 98: Functional Database Strategies at Scala Bay

It’s Like Having Control Over The Versions Of

Your State Changes

Page 99: Functional Database Strategies at Scala Bay

It’s Like Having Control Over The Versions Of

Your Data

Page 100: Functional Database Strategies at Scala Bay

It’s Like GitFor Your Data

Page 101: Functional Database Strategies at Scala Bay

1. Frankly, It’s Weird2. Requires Events. No Events, No Event-Sourcing.3. As Of March 2017, It’s Still Non-Standard

Reasons Against Event-Sourcing

Page 102: Functional Database Strategies at Scala Bay

Wait! We’reScala

developers!

Page 103: Functional Database Strategies at Scala Bay

Who Cares About BeingNon-Standard?

Page 104: Functional Database Strategies at Scala Bay

That About Sums Up Event Sourcing

Page 105: Functional Database Strategies at Scala Bay

That About Sums Up Database

Interactions

Page 106: Functional Database Strategies at Scala Bay

Okay, Actually That’s The Entire Talk

Unless There’s More Time

Page 107: Functional Database Strategies at Scala Bay

Functional Database Strategies

Scala Bay • March 20, 2017

Page 108: Functional Database Strategies at Scala Bay

by Jason Swartz@swartzrock

Page 109: Functional Database Strategies at Scala Bay

Thank You For Attending

Page 110: Functional Database Strategies at Scala Bay

Fin

Page 111: Functional Database Strategies at Scala Bay

THIS SPACELEFT BLANK