Skip to content

Add optional persistent sessions across PHP requests#151

Merged
msyk merged 1 commit intomsyk:masterfrom
filiptorphage-mjuk:feature/persistent-sessions
Apr 22, 2026
Merged

Add optional persistent sessions across PHP requests#151
msyk merged 1 commit intomsyk:masterfrom
filiptorphage-mjuk:feature/persistent-sessions

Conversation

@filiptorphage-mjuk
Copy link
Copy Markdown
Contributor

This PR adds optional support for reusing a FileMaker Data API access token across multiple PHP requests, as discussed in issue #150.

It introduces:

  • PersistentSession
  • SessionCacheInterface
  • ApcuSessionCache
  • persistent-session integration in FMDataAPI

The intended flow is:

  1. restore a cached token at the beginning of a request,
  2. use that token locally during the request,
  3. if it is no longer valid, clear it,
  4. log in again,
  5. cache the new token,
  6. retry once.

The feature is optional. FMDataAPI continues to work without APCu, but persistent-session support requires either APCu or a user-provided SessionCacheInterface implementation.

One current limitation is that the retry logic does not yet fully work when setThrowException(true) is enabled, because the error state is not always populated before an exception is thrown in the lower-level request flow. This does not currently work since errorCode() hasn't been populated here. I believe the best solution would be to make sure storeToProperties() is always called after callRestAPI(), even when an exception is thrown.

The intended split is:

  • startCommunication() for keeping a session open within one PHP request
  • beginPersistentSession() for reusing a session across multiple PHP requests

Feedback

This PR is my proposed implementation of the feature request.

  • Would you consider it reasonable to use APCu as the default cache implementation, while not making it a requirement?

If you have any feedback or just opinions, feel free to bring them up.

@filiptorphage-mjuk filiptorphage-mjuk marked this pull request as draft April 21, 2026 16:14
@filiptorphage-mjuk
Copy link
Copy Markdown
Contributor Author

I am changing this to a draft since I will want to look at this some further. Some parts may change until I'm ready with it, but this should be a good starting point of what I was trying to accomplish.

@filiptorphage-mjuk
Copy link
Copy Markdown
Contributor Author

I see that this is essentially two different features, persistent sessions and a retry mechanism. I'll move these to different PRs as they are not dependent on each other.

@msyk
Copy link
Copy Markdown
Owner

msyk commented Apr 22, 2026

@filiptorphage-mjuk, Thanks for committing fine code! I think there is no issues on your pull request. I will merge.

@msyk msyk marked this pull request as ready for review April 22, 2026 01:15
@msyk msyk merged commit c42e51f into msyk:master Apr 22, 2026
62 checks passed
@filiptorphage-mjuk
Copy link
Copy Markdown
Contributor Author

I did point out a flaw of this PR that needed to be fixed (it's currently broken), which is why I changed it to a draft. And there were some things that I would have preferred to have a second look at first.
I guess I'm not used to making PRs to public repos, but I would have assumed a draft PR wasn't completely ready.

  • The execute function does not refresh a token correctly when setThrowInException(true), this is because errorCode() not being accurate, and only contain the error code of the previous request (not current). This I was hoping to discuss a solution before merging, as this actively needs a fix.
  • i also think a better name than execute could be chosen, as it is essentially just a retry logic of a token expires.
  • Internally we have also discussed whether it would make more sense to merge startCommunication() and beginPersistentSession() into just a startCommunication(). The idea here would be to check whether $this->persistentSession is null or not. If it's null (default), then perform the old functionality of startCommunication(), but if it's set, change it's behavior to what beginPersistentSession() currently does. That would have removed the possibility of accidentally running this PR's beginPersistentSession() which could throw a RuntimeException. But whether this would be a better idea we would leave to you in the end (this point)
  • We haven't looked into if the PersistentSession class actually provides enough justification to exist, or if it's helpers could be used directly.

There might be more things, but now that you have actually merged this PR, what would you recommend to be the best course of action? @msyk

@filiptorphage-mjuk
Copy link
Copy Markdown
Contributor Author

@msyk, I would like to make some adjustments before I think this is ready to be merged, I was too hasty with creating this PR as I didn't expect it to be merged so soon. Would you prefer to revert this PR, or for me to simply create a new PR with just the adjustments I would like to make?

@msyk
Copy link
Copy Markdown
Owner

msyk commented Apr 22, 2026

OK. I will back to it.

@msyk
Copy link
Copy Markdown
Owner

msyk commented Apr 24, 2026

@filiptorphage-mjuk

There might be more things, but now that you have actually merged this PR, what would you recommend to be the best course of action?

Could you open the new issue to discuss your proposals?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants