Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Caching in OfferProvider
- - Why? - To improve performance (that is not call db an each provider request).
- - Where? - At the point of fething data from `OfferProvider` component (repositories).
- - How? - By using `Rails.cache#fetch`
- ## Introduction
- Why we don't like caching?
- - cache keys? (we don't know how to name the keys)
- - cache invalidaiton? (we are fraid that after updating record, app will still serve old data)
- - cache size? (ActiveRecord models when serialized can grow of of controll)
- That 3 points above we makes caching not a trivial task and IMHO that's why developers tend to avoid it.
- Hovewer, because in `OfferProvider`:
- - we don't write do db in any other way than throught repository
- - we don't read in any other way than throught repository
- - and we use dry-structs as data containers (not AR models)
- In other words, because we encapsulate data access by Repository - cache becomes simple to manage.
- In next sections I'd like to present my proposal.
- ### Repositories encapsulates data access (reads and writes to db)
- __Read:__
- ```ruby
- def find(id, provider_id)
- build_from_record(find_record(id, provider_id))
- end
- # with cache:
- def find(id, provider_id)
- Rails.cache.fetch('cache_key_will_be_described_later') do
- build_from_record(find_record(id, provider_id))
- end
- end
- ```
- __Write:__
- ```ruby
- def update(provider_id:, id:, changeset:)
- record = find_record(id, provider_id)
- record.update!(update_query_params(changeset.to_h))
- build_from_record(record)
- end
- # with cache
- def update(provider_id:, id:, changeset:)
- record = find_record(id, provider_id)
- record.update!(update_query_params(changeset.to_h))
- invalidate_cache(provider_id)
- build_from_record(record)
- end
- ```
- ### Repositories methods and their parameters define the cache key.
- Cache key will depend on methods parameters.
- eg. for:
- `find(id, provider_id)`
- cache key: "providers_#{provider_id}_#{id}_find"
- ### Repositories modify data
- Currently we have 3 methods in OfferProvider repository (create, update, delete).
- That simplifies cache invalidation.
- Cache will be invalidated only in these methods.
- ### We control cache size thanks to dry-stucts
- How data are stored in cache?
- Data is serialized on write to cache and deserialized on reading from cache.
- In our cache we will cache our dry-structs, so it's lightweight and we completely controll it.
- ## Example
- ```
- @startuml
- "Controller/Service" -> Repository : find_by(a, b)
- Repository -> Record : find_by(a, b)
- Repository <-- Record : record
- Repository -> Factory : build_from_record(record)
- Repository <-- Factory : entity
- "Controller/Service" <-- Repository : entity
- box "Persistence layer" #LightBlue
- participant Repository
- participant Record
- participant Factory
- end box
- @enduml
- ```
Add Comment
Please, Sign In to add comment