Top Banner
Functional Database Strategies Scala Bay • March 20, 2017
111

Functional Database Strategies at Scala Bay

Apr 05, 2017

Download

Technology

Jason Swartz
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
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