0

This is a pretty standard problem but I'm not sure what the standard answer is in Scala, especially a Scala / Scala.js system.

Given that you have a domain consisting of:

  • Contractor
  • Agent
  • Agency
  • Invoice

with the relations:

  • Contractor -[has_agent]-> Agent
  • Agent -[has_agency]-> Agency
  • Agency -[has_Inoivce]-> Invoice

The domain is stored in an SQL database and read into Scala case classes on the server side using Slick. Case classes correspond to rows in database tables and foreign keys are used to create more complex (nested) case classes. E.g. the case class for a Contractor:

case class Contractor(
    id:    Int,
    name:  String,
    agent: Agent
)

and an Agent

case class Agent(
    id:     Int,
    name:   String,
    agency: Agency
)

The server serializes the case classes into JSON for delivery to the client.

When deserialized back into case classes on the client (thanks to scala-js) each fetched set of data forms its own isolated object graph. If two Contractors were fetched and they both had the same Agent, they would contain duplicate sets of the rest of the chain up to Agency. If the information in one object graph is changed on the client or is updated by fetching again later there is a large risk of having data out of sync.

In fact, two copies can appear on the server too because a copy gets created each time a given row is read from the database. But on the server they are short-lived.

It wouldn't be conceptually difficult to build some collections on the client and ensure there is only a ever a single copy of each object, but it's work and it's a general problem.

Is there a standard framework to use? A caching framework perhaps? Best suited to Scala with Scala.js (with Slick and Play and MySQL)?

1 Answers1

2

I would start with not having nested objects in the JSON. I would model relations by having a unique ID for each distinct entity. You probably already have this, as a foreign key to support joins.

Example case class:

case class Contractor(
  id:    ContractorId, //Prefer typed Ids (wrapped values) instead of primitives.
  name:  String
  agent: AgentId
)

Then you could use something like Diode on the client, maybe with a ReftTo for the related entities.

Per Wiklander
  • 1,054
  • 9
  • 19