-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Overhaul and deprotocolize Network 🛰 #218
Conversation
I like these changes. It reduces complexity on the network stack implementation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing work 💪
Thanks for the spring/summer cleaning on the network layer 🥇
As it was, our `NetworkStack` and it's main conforming type `URLSessionNetworkStack` were not straightforward to use, mostly because of the many different `Resource` protocols and respective associated types. All these `Resource` protocols, while being broken into simple, focused and composable units, created lots of complexity due to the generic constraints they impose. While initially designed for allowing diverse `NetworkStack`'s to be modeled, we have observed that most of the times users are simply interested in using a `URLSessionNetworkStack`. The `NetworkStore` suffered from similar issues, by being tied to our huge `Resource` protocol family, while its main idea (and sole implementation) was a store that orchestrated both a network and persistence stacks. Finally, `PersistenceStack` received a minor clean up and improvement to make it more flexible and powerful. With all these things in mind, our `Resource` "family" was rethought to be composed of multiple witnesses, instead of multiple protocols. Witnesses provide the same abstraction of modeling behavior, without some of the limitations and complexities of protocols. By being generic concrete types, they also allow creating default implementations via static properties and functions, making code reuse very simple. The `NetworkStack` protocol was kept but greatly simplified and the `NetworkStore` protocol was discontinuated in favor of a `StackOrchestratorStore`, also simplified while making its purpose clearer. ## Changes - Deprecate all `Resource` protocols. - Create new `BaseRequestMaking` witness to replace `BaseRequestResource`. - Create new `ModelDecoding` witness to replace `DecodableResource`. - Create new `ErrorDecoding` witness to replace `ExternalErrorDecoderResource`. - Deprecate `RequestAuthenticator` in favor of `URLRequestAuthenticator`, providing a simpler API. - Deprecate `RequestInterceptor` in favour of a more powerful `URLSessionResourceInterceptor` defined at a Resource level, allowing much more flexibility and control. Add default conformances to `URLRequestAuthenticator`, `Network.URLSessionRetryPolicy`. - Improve `Retry` infrastructure: + Create new `Retry.State` to model the retry state of an arbitrary operation, update `Policy.shouldRetry()` to use it. + Create `Retry.Action.CompareClosure` to compare actions. + Create `Retry.Action.mostPrioritary` helper static function, with the default logic to pick the most prioritary action between two. + Rename `Retry.Policy.retries` to `maxRetries`. + Rename `Retry.Policy.Backoff.Truncation.retries` to `maxRetries`. + Rename `Retry.Policy.Backoff.Truncation.delay` to `maxDelay`. - Improve `HTTPResourceEndpoint`: + Convert `body` property into a throwable function, to allow handling enconding errors. + Convert `request` computed property into a throwable function, to propagate body encoding errors. - Rename `Network.URLSessionNetworkStack.Error` to `Network.URLSessionError` and improve it: + Remove `URLResponse` associated value from `.url` and `.retry` + Use new `Retry.State` - Update `NetworkStack` to require just a `Resource` and `FetchError` associated types, and add protocol extension to perform decoding after a network fetch. - Update Network playground with recent changes. - Improve `PersistenceStack` to have a new `Key: Hashable` `associatedtype` instead of the hardcoded `Persistence.Key`, and renamed existing `Remote` to `Payload`. - Deprecate `NetworkStore` in favor of `StackOrchestratorStore`, which requires a `NetworkStack` and `PersistenceStack associated types. Add a protocol extension to perform decoding after a fetch. - Create new `StackOrchestrator` namespace. - Rename `NetworkPersistableStore` to `StackOrchestrator.Store`, plus some internal adjustments. - Rename `NetworkStorePerformanceMetricsTracker` to `StackOrchestratorPerformanceMetricsTracker`. - Update `podspec`. - Add some new rule exceptions on `.swiftlint.yml`
- Remove `Network.URLSessionNetworkStack.Configuration` - Create `FetchAndDecodeError`. - Move `ModelDecoding` out of `Network` namespace. - Improve default decoding witnesses helpers.
3d0856a
to
fecb2ea
Compare
Codecov Report
@@ Coverage Diff @@
## master #218 +/- ##
==========================================
+ Coverage 94.81% 94.94% +0.12%
==========================================
Files 100 102 +2
Lines 3243 3345 +102
==========================================
+ Hits 3075 3176 +101
- Misses 168 169 +1
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👏 Great work! These changes should simplify the use of this lib. Left just some very minor comments
Checklist
master
Motivation and Context
As it was, our
NetworkStack
and it's main conforming typeURLSessionNetworkStack
were not straightforward to use, mostly because of the many differentResource
protocols and respectiveassociated types. All these
Resource
protocols, while being broken into simple, focused and composable units, created lots of complexity due to the generic constraints they impose.While initially designed for allowing diverse
NetworkStack
's to be modeled, we have observed that most of the times users are simply interested in using aURLSessionNetworkStack
.The
NetworkStore
suffered from similar issues, by being tied to our hugeResource
protocol family, while its main idea (and sole implementation) was a store that orchestrated both a network and persistence stacks.Finally,
PersistenceStack
received a minor clean up and improvement to make it more flexible and powerful.With all these things in mind, our
Resource
"family" was rethought to be composed of multiple witnesses, instead of multiple protocols. Witnesses provide the same abstraction of modeling behavior, without some of the limitations and complexities of protocols. By being genericconcrete types, they also allow creating default implementations via static properties and functions, making code reuse very simple.
The
NetworkStack
protocol was kept but greatly simplified and theNetworkStore
protocol was discontinuated in favor of aStackOrchestratorStore
, also simplified while making its purpose clearer.Some concepts discussed on the amazing pointfree's videos were used, in particular protocol witnesses. Feel free to check this talk or their video series over at pointfree.co. 🤓🙏
Description
Deprecate all
Resource
protocols, and replace most relevant ones with witnesses:Create new
BaseRequestMaking
witness to replaceBaseRequestResource
.Create new
ModelDecoding
witness to replaceDecodableResource
.Create new
ErrorDecoding
witness to replaceExternalErrorDecoderResource
.Deprecate
RequestAuthenticator
in favor ofURLRequestAuthenticator
, providing a simpler API.Deprecate
RequestInterceptor
in favour of a more powerfulURLSessionResourceInterceptor
defined at a Resource level, allowing much more flexibility and control. Add default conformances toURLRequestAuthenticator
,Network.URLSessionRetryPolicy
.Improve
Retry
infrastructure via newRetry.State
,Retry.Action.CompareClosure
andRetry.Action.mostPrioritary
helper static function. RenameRetry.Policy.retries
tomaxRetries
,Retry.Policy.Backoff.Truncation.retries
tomaxRetries
andRetry.Policy.Backoff.Truncation.delay
tomaxDelay
.Improve
HTTPResourceEndpoint
:Convert
body
property into a throwable function, to allow handling encoding errors.Convert
request
computed property into a throwable function, to propagate body encoding errors.Rename
Network.URLSessionNetworkStack.Error
toNetwork.URLSessionError
and refine it by removing unnecessaryURLResponse
and using newRetry.State
.Update
NetworkStack
to require just aResource
andFetchError
associated types, and add protocol extension to perform decoding after a network fetch.Update Network playground with recent changes.
Improve
PersistenceStack
to have a newKey: Hashable
associatedtype
instead of the hardcodedPersistence.Key
, and renamed existingRemote
toPayload
.Deprecate
NetworkStore
in favor ofStackOrchestratorStore
, which requires aNetworkStack
and `PersistenceStack associated types. Add a protocol extension to perform decoding after a fetch.Create new
StackOrchestrator
namespace.Rename
NetworkPersistableStore
toStackOrchestrator.Store
, plus some internal adjustments.Rename
NetworkStorePerformanceMetricsTracker
toStackOrchestratorPerformanceMetricsTracker
.Update
podspec
.Add some new rule exceptions on
.swiftlint.yml