1

When I start my app (simulator or on phone) after some time has passed (e.g. some hours), Siesta won't load my resources and the statusOverlay() will be shown indefinitely.

In detail, I have a HomeViewController, which issues the following request onViewAppear:

Api.currentUser.loadIfNeeded()
Api.events.loadIfNeeded()
Api.recommendedProducts.loadIfNeeded()

In my viewDidLoad I have specified individual resource observers as follows:

statusOverlay.embed(in: self)
Api.currentUser.addObserver(statusOverlay).addObserver(owner: self){
        [weak self] resource, _ in
        if(resource.isUpToDate){
            self?.setWelcomeMessage(user: resource.typedContent())
        }
}

Api.events.addObserver(statusOverlay).addObserver(owner: self){
        [weak self] resource, _ in
        if(resource.isUpToDate){
            self?.setEvents(events: resource.typedContent())
        }
}

Api.recommendedProducts.addObserver(statusOverlay).addObserver(owner: self){
        [weak self] resource, _ in
        if(resource.isUpToDate){
            self?.setRecommendedProducts(products: resource)
        }
}

Resources and the Siesta instance are defined in the Api class. While this code works well on regular uses of the app, it struggles when the app was in background or closed for some time.

Full Siesta logging results in the following (the bearer token is valid, but truncated for readability):

Siesta:network        │ Cache request for Resource(…/user/5b0553d15e70bf00104224fc)[]
Siesta:staleness      │ Resource(…/user/5b0553d15e70bf00104224fc)[] is not up to date: no error | no data
Siesta:staleness      │ Resource(…/user/5b0553d15e70bf00104224fc)[] is not up to date: no error | no data
Siesta:configuration  │ Computing configuration for GET Resource(…/event?dir=desc&order=ends_at)[]
Siesta:configuration  │   ├╴Applying config 0 [Siesta standard text parsing]
Siesta:configuration  │   ├╴Applying config 1 [Siesta standard image parsing]
Siesta:configuration  │   ├╴Applying config 6 [/event : Data → Array<Event>]
Siesta:configuration  │   ├╴Applying config 20 [**]
Siesta:configuration  │   └╴Resulting configuration 
Siesta:configuration  │       expirationTime:            30.0 sec
Siesta:configuration  │       retryTime:                 1.0 sec
Siesta:configuration  │       progressReportingInterval: 0.05 sec
Siesta:configuration  │       headers (1)
Siesta:configuration  │         Authorization: Bearer ABCDE
Siesta:configuration  │       requestDecorators: 0
Siesta:configuration  │       pipeline
Siesta:configuration  │         ║ rawData stage (no transformers)
Siesta:configuration  │         ║ decoding stage (no transformers)
Siesta:configuration  │         ║ parsing stage
Siesta:configuration  │         ╟   ⟨text/*⟩ Data → String  [transformErrors: true]
Siesta:configuration  │         ╟   ⟨image/*⟩ Data → UIImage
Siesta:configuration  │         ║ model stage
Siesta:configuration  │         ╟   Data → Array<Event>
Siesta:configuration  │         ║ cleanup stage (no transformers)
Siesta:network        │ Cache request for Resource(…/event?dir=desc&order=ends_at)[]
Siesta:staleness      │ Resource(…/event?dir=desc&order=ends_at)[] is not up to date: no error | no data
Siesta:staleness      │ Resource(…/event?dir=desc&order=ends_at)[] is not up to date: no error | no data
Siesta:configuration  │ Computing configuration for GET Resource(…/my/recommended/products)[]
Siesta:configuration  │   ├╴Applying config 0 [Siesta standard text parsing]
Siesta:configuration  │   ├╴Applying config 1 [Siesta standard image parsing]
Siesta:configuration  │   ├╴Applying config 5 [/my/recommended/products : Data → Array<Product>]
Siesta:configuration  │   ├╴Applying config 20 [**]
Siesta:configuration  │   └╴Resulting configuration 
Siesta:configuration  │       expirationTime:            30.0 sec
Siesta:configuration  │       retryTime:                 1.0 sec
Siesta:configuration  │       progressReportingInterval: 0.05 sec
Siesta:configuration  │       headers (1)
Siesta:configuration  │         Authorization: Bearer ABCDE
Siesta:configuration  │       requestDecorators: 0
Siesta:configuration  │       pipeline
Siesta:configuration  │         ║ rawData stage (no transformers)
Siesta:configuration  │         ║ decoding stage (no transformers)
Siesta:configuration  │         ║ parsing stage
Siesta:configuration  │         ╟   ⟨text/*⟩ Data → String  [transformErrors: true]
Siesta:configuration  │         ╟   ⟨image/*⟩ Data → UIImage
Siesta:configuration  │         ║ model stage
Siesta:configuration  │         ╟   Data → Array<Product>
Siesta:configuration  │         ║ cleanup stage (no transformers)
Siesta:network        │ Cache request for Resource(…/my/recommended/products)[]
Siesta:staleness      │ Resource(…/my/recommended/products)[] is not up to date: no error | no data
Siesta:staleness      │ Resource(…/my/recommended/products)[] is not up to date: no error | no data
Siesta:staleness      │ Resource(…/user/5b0553d15e70bf00104224fc)[] is not up to date: no error | no data
Siesta:network        │ Chain[Request:6000001d68f0(Cache request for Resource(…/user/5b0553d15e70bf00104224fc)[])]
Siesta:networkDetails │ Cache request for Resource(…/user/5b0553d15e70bf00104224fc)[] already started
Siesta:staleness      │ Resource(…/event?dir=desc&order=ends_at)[] is not up to date: no error | no data
Siesta:network        │ Chain[Request:60c0003c2df0(Cache request for Resource(…/event?dir=desc&order=ends_at)[])]
Siesta:networkDetails │ Cache request for Resource(…/event?dir=desc&order=ends_at)[] already started
Siesta:staleness      │ Resource(…/my/recommended/products)[] is not up to date: no error | no data
Siesta:network        │ Chain[Request:6080001de4b0(Cache request for Resource(…/my/recommended/products)[])]
Siesta:networkDetails │ Cache request for Resource(…/my/recommended/products)[] already started
Siesta:configuration  │ Configurations need to be recomputed
Siesta:stateChanges   │ Resource(…/event?dir=desc&order=ends_at)[L] wiped
Siesta:network        │ Cancelled Chain[Request:60c0003c2df0(Cache request for Resource(…/event?dir=desc&order=ends_at)[])]
Siesta:network        │ Cancelled Cache request for Resource(…/event?dir=desc&order=ends_at)[]
Siesta:observers      │ Resource(…/event?dir=desc&order=ends_at)[L] sending newData(wipe) event to 2 observers
Siesta:observers      │   ↳ newData(wipe) → <Siesta.ResourceStatusOverlay: 0x7fbe105369a0; frame = (0 0; 320 568); hidden = YES; layer = <CALayer: 0x6080002347c0>>
Siesta:observers      │   ↳ newData(wipe) → ClosureObserver(HomeViewController.swift:66)
Siesta:configuration  │ Computing configuration for GET Resource(…/event?dir=desc&order=ends_at)[L]
Siesta:configuration  │   ├╴Applying config 0 [Siesta standard text parsing]
Siesta:configuration  │   ├╴Applying config 1 [Siesta standard image parsing]
Siesta:configuration  │   ├╴Applying config 6 [/event : Data → Array<Event>]
Siesta:configuration  │   ├╴Applying config 20 [**]
Siesta:configuration  │   └╴Resulting configuration 
Siesta:configuration  │       expirationTime:            30.0 sec
Siesta:configuration  │       retryTime:                 1.0 sec
Siesta:configuration  │       progressReportingInterval: 0.05 sec
Siesta:configuration  │       headers (1)
Siesta:configuration  │         Authorization: Bearer ABCDE
Siesta:configuration  │       requestDecorators: 0
Siesta:configuration  │       pipeline
Siesta:configuration  │         ║ rawData stage (no transformers)
Siesta:configuration  │         ║ decoding stage (no transformers)
Siesta:configuration  │         ║ parsing stage
Siesta:configuration  │         ╟   ⟨text/*⟩ Data → String  [transformErrors: true]
Siesta:configuration  │         ╟   ⟨image/*⟩ Data → UIImage
Siesta:configuration  │         ║ model stage
Siesta:configuration  │         ╟   Data → Array<Event>
Siesta:configuration  │         ║ cleanup stage (no transformers)
Siesta:staleness      │ Resource(…/event?dir=desc&order=ends_at)[L] is not up to date: no error | no data
Siesta:staleness      │ Resource(…/event?dir=desc&order=ends_at)[L] is not up to date: no error | no data
Siesta:network        │ Cache request for Resource(…/event?dir=desc&order=ends_at)[L]
Siesta:stateChanges   │ Resource(…/user/5b0553d15e70bf00104224fc)[L] wiped
Siesta:network        │ Cancelled Chain[Request:6000001d68f0(Cache request for Resource(…/user/5b0553d15e70bf00104224fc)[])]
Siesta:network        │ Cancelled Cache request for Resource(…/user/5b0553d15e70bf00104224fc)[]
Siesta:observers      │ Resource(…/user/5b0553d15e70bf00104224fc)[L] sending newData(wipe) event to 1 observer
Siesta:observers      │   ↳ newData(wipe) → ClosureObserver(HomeViewController.swift:56)
Siesta:configuration  │ Computing configuration for GET Resource(…/user/5b0553d15e70bf00104224fc)[L]
Siesta:configuration  │   ├╴Applying config 0 [Siesta standard text parsing]
Siesta:configuration  │   ├╴Applying config 1 [Siesta standard image parsing]
Siesta:configuration  │   ├╴Applying config 2 [/user/* : Data → User]
Siesta:configuration  │   ├╴Applying config 20 [**]
Siesta:configuration  │   └╴Resulting configuration 
Siesta:configuration  │       expirationTime:            30.0 sec
Siesta:configuration  │       retryTime:                 1.0 sec
Siesta:configuration  │       progressReportingInterval: 0.05 sec
Siesta:configuration  │       headers (1)
Siesta:configuration  │         Authorization: Bearer ABCDE
Siesta:configuration  │       requestDecorators: 0
Siesta:configuration  │       pipeline
Siesta:configuration  │         ║ rawData stage (no transformers)
Siesta:configuration  │         ║ decoding stage (no transformers)
Siesta:configuration  │         ║ parsing stage
Siesta:configuration  │         ╟   ⟨text/*⟩ Data → String  [transformErrors: true]
Siesta:configuration  │         ╟   ⟨image/*⟩ Data → UIImage
Siesta:configuration  │         ║ model stage
Siesta:configuration  │         ╟   Data → User
Siesta:configuration  │         ║ cleanup stage (no transformers)
Siesta:staleness      │ Resource(…/user/5b0553d15e70bf00104224fc)[L] is not up to date: no error | no data
Siesta:staleness      │ Resource(…/user/5b0553d15e70bf00104224fc)[L] is not up to date: no error | no data
Siesta:network        │ Cache request for Resource(…/user/5b0553d15e70bf00104224fc)[L]
Siesta:stateChanges   │ Resource(…/my/recommended/products)[L] wiped
Siesta:network        │ Cancelled Chain[Request:6080001de4b0(Cache request for Resource(…/my/recommended/products)[])]
Siesta:network        │ Cancelled Cache request for Resource(…/my/recommended/products)[]
Siesta:observers      │ Resource(…/my/recommended/products)[L] sending newData(wipe) event to 2 observers
Siesta:observers      │   ↳ newData(wipe) → ClosureObserver(HomeViewController.swift:76)
Siesta:configuration  │ Computing configuration for GET Resource(…/my/recommended/products)[L]
Siesta:configuration  │   ├╴Applying config 0 [Siesta standard text parsing]
Siesta:configuration  │   ├╴Applying config 1 [Siesta standard image parsing]
Siesta:configuration  │   ├╴Applying config 5 [/my/recommended/products : Data → Array<Product>]
Siesta:configuration  │   ├╴Applying config 20 [**]
Siesta:configuration  │   └╴Resulting configuration 
Siesta:configuration  │       expirationTime:            30.0 sec
Siesta:configuration  │       retryTime:                 1.0 sec
Siesta:configuration  │       progressReportingInterval: 0.05 sec
Siesta:configuration  │       headers (1)
Siesta:configuration  │         Authorization: Bearer ABCDE
Siesta:configuration  │       requestDecorators: 0
Siesta:configuration  │       pipeline
Siesta:configuration  │         ║ rawData stage (no transformers)
Siesta:configuration  │         ║ decoding stage (no transformers)
Siesta:configuration  │         ║ parsing stage
Siesta:configuration  │         ╟   ⟨text/*⟩ Data → String  [transformErrors: true]
Siesta:configuration  │         ╟   ⟨image/*⟩ Data → UIImage
Siesta:configuration  │         ║ model stage
Siesta:configuration  │         ╟   Data → Array<Product>
Siesta:configuration  │         ║ cleanup stage (no transformers)
Siesta:staleness      │ Resource(…/my/recommended/products)[L] is not up to date: no error | no data
Siesta:staleness      │ Resource(…/my/recommended/products)[L] is not up to date: no error | no data
Siesta:observers      │   ↳ newData(wipe) → <Siesta.ResourceStatusOverlay: 0x7fbe105369a0; frame = (0 0; 320 568); layer = <CALayer: 0x6080002347c0>>
Siesta:network        │ Cache request for Resource(…/my/recommended/products)[L]
Siesta:networkDetails │ Received response, but request was already cancelled: Cache request for Resource(…/user/5b0553d15e70bf00104224fc)[] 
Siesta:networkDetails │     New response: RequestError(userMessage: "Cache miss", httpStatusCode: nil, entity: nil, cause: Optional(Siesta.RequestError.Cause.CacheMiss()), timestamp: 553608424.06342196)
Siesta:networkDetails │ Received response, but request was already cancelled: Cache request for Resource(…/event?dir=desc&order=ends_at)[] 
Siesta:networkDetails │     New response: RequestError(userMessage: "Cache miss", httpStatusCode: nil, entity: nil, cause: Optional(Siesta.RequestError.Cause.CacheMiss()), timestamp: 553608424.07201898)
Siesta:networkDetails │ Received response, but request was already cancelled: Cache request for Resource(…/my/recommended/products)[] 
Siesta:networkDetails │     New response: RequestError(userMessage: "Cache miss", httpStatusCode: nil, entity: nil, cause: Optional(Siesta.RequestError.Cause.CacheMiss()), timestamp: 553608424.08093095)
Siesta:staleness      │ Resource(…/user/5b0553d15e70bf00104224fc)[L] is not up to date: no error | no data
Siesta:staleness      │ Resource(…/user/5b0553d15e70bf00104224fc)[L] is not up to date: no error | no data
Siesta:staleness      │ Resource(…/event?dir=desc&order=ends_at)[L] is not up to date: no error | no data
Siesta:staleness      │ Resource(…/event?dir=desc&order=ends_at)[L] is not up to date: no error | no data
Siesta:staleness      │ Resource(…/my/recommended/products)[L] is not up to date: no error | no data
Siesta:staleness      │ Resource(…/my/recommended/products)[L] is not up to date: no error | no data
Siesta:staleness      │ Resource(…/user/5b0553d15e70bf00104224fc)[L] loadIfNeeded(): load is already in progress: Request:6000001d6bc0(Chain[Request:6000001d68f0(Cache request for Resource(…/user/5b0553d15e70bf00104224fc)[])])
Siesta:staleness      │ Resource(…/event?dir=desc&order=ends_at)[L] loadIfNeeded(): load is already in progress: Request:60c0003c2ee0(Chain[Request:60c0003c2df0(Cache request for Resource(…/event?dir=desc&order=ends_at)[])])
Siesta:staleness      │ Resource(…/my/recommended/products)[L] loadIfNeeded(): load is already in progress: Request:60c0003c2fd0(Chain[Request:6080001de4b0(Cache request for Resource(…/my/recommended/products)[])])

In effect, there are no GET requests issued and the statusOverlay remains visible.

Doing a full restart of the app does the trick, but this is of course not suitable for end users.

Do you have any ideas how I can fix this issue? Many Thanks in advance!

Jan
  • 33
  • 3

1 Answers1

0

This section of the log:

Siesta:stateChanges   │ Resource(…/user/5b0553d15e70bf00104224fc)[L] wiped
Siesta:network        │ Cancelled Chain[Request:6000001d68f0(Cache request for Resource(…/user/5b0553d15e70bf00104224fc)[])]
Siesta:network        │ Cancelled Cache request for Resource(…/user/5b0553d15e70bf00104224fc)[]
Siesta:observers      │ Resource(…/user/5b0553d15e70bf00104224fc)[L] sending newData(wipe) event to 1 observer
Siesta:observers      │   ↳ newData(wipe) → ClosureObserver(HomeViewController.swift:56)

…suggests that you’re calling either Siesta.wipeResources() or Resource.wipe(). That causes any outstanding requests for the resource to be cancelled. Perhaps you are wiping resources after a timeout? Or when app is foregrounded?

If you want to immediately trigger a new load after wiping the resources, then have your observer call loadIfNeeded() if resource.latestData is nil.

Paul Cantrell
  • 9,175
  • 2
  • 40
  • 48
  • Thank you Paul! I do call `wipeResources()` when I get a new bearer Token (which takes place in this case). Now I changed my observer to: `Api.events.addObserver(statusOverlay).addObserver(owner: self){ [weak self] resource, _ in if(resource.isUpToDate){ self?.setEvents(events: resource.typedContent()) } else if (resource.latestData == nil){ resource.loadIfNeeded() } }` However, this didn't do the trick. What helped was to delay the resource request by .1 second (race condition?). – Jan Jul 19 '18 at 06:43