Skip to content

Fix stream cache semantics for PUT vs PATCH and include TobyFix package/namespace rename#332

Open
canedha wants to merge 2 commits intostep-up-labs:masterfrom
canedha:fix/stream-put-replace-patch-merge
Open

Fix stream cache semantics for PUT vs PATCH and include TobyFix package/namespace rename#332
canedha wants to merge 2 commits intostep-up-labs:masterfrom
canedha:fix/stream-put-replace-patch-merge

Conversation

@canedha
Copy link
Copy Markdown

@canedha canedha commented Mar 17, 2026

Summary

This PR fixes an issue in the streaming cache logic where put and patch events were effectively handled with the same merge behavior.

For Firebase Realtime Database REST streaming, these two event types have different semantics: put should replace the data at the target path, while patch should merge into the existing data at the target path. Before this change, the cache update path used merge-style behavior for both event types, which could leave stale properties behind when an object was replaced by a put event and the new payload no longer contained fields that had existed before.

Root cause

The streaming code already receives distinct Firebase server event types (put vs patch), but that distinction was not preserved when data was pushed into the cache.

In FirebaseSubscription.ProcessServerData(...), both Put and Patch eventually went through the same cache call. Inside FirebaseCache.PushData(...), object updates ended up using merge-style population logic. That behavior is correct for patch, but incorrect for put.

Because of that, if a cached object previously contained a property that was no longer present in a later full replacement payload, the cache could merge the new payload into the existing object and leave the old property behind instead of removing it.

Changes

  • Preserve the actual Firebase server event type when pushing into the cache.

    File:

    • src/Firebase/Streaming/FirebaseSubscription.cs

    Change:

    • ProcessServerData(...) now passes the received FirebaseServerEventType into the cache layer, instead of treating put and patch the same at that boundary.
  • Split cache behavior by event semantics.

    File:

    • src/Firebase/Streaming/FirebaseCache.cs

    Changes:

    • Added an overload of PushData(...) that accepts FirebaseServerEventType
    • Kept the old overload as a compatibility wrapper
    • Implemented different cache behavior for Put and Patch

    New semantics:

    • Put replaces dictionary contents instead of merging them
    • Put replaces object/property values at the target path instead of merge-populating them
    • Patch keeps existing merge behavior
    • Patch only applies the incoming keys/properties to the existing cached object

    This restores the correct realtime cache semantics and prevents stale properties from surviving a full object replacement.

  • Package / assembly / namespace rename to TobyFix.

    Files:

    • src/Firebase/Firebase.csproj
    • multiple source files under src/Firebase/...

    Changes:

    • package renamed to FirebaseDatabase.net-TobyFix
    • assembly renamed to FirebaseDatabase.net.TobyFix
    • namespaces moved to Firebase.TobyFix...

    This rename is included because the downstream consumer uses the patched package under a clearly separated identity and should not mix it with the original package.

Why this matters

Without this fix, the stream cache can diverge from the actual Firebase state after a put event. A full object replacement can behave like a partial merge, which means removed properties may incorrectly remain in cached objects. After this fix, put replaces the target state and patch continues to merge incremental changes.

Files touched

  • Functional fix:

    • src/Firebase/Streaming/FirebaseSubscription.cs
    • src/Firebase/Streaming/FirebaseCache.cs
  • Package / identity rename:

    • src/Firebase/Firebase.csproj
    • renamed namespaces/usings across src/Firebase/...

Validation performed

Validated against a real downstream client setup using Firebase Realtime Database streaming.

Test scenario:

  • an existing object is updated through a realtime stream event
  • the new payload represents a full replacement and omits fields that previously existed
  • before this fix, stale properties could remain in the cached object
  • after this fix, the cached object correctly reflects the replacement payload and stale properties no longer remain

Observed result:

  • realtime behavior now matches the expected semantics for put and patch

Notes

This PR includes both:

  • the functional PUT/PATCH cache fix
  • the TobyFix package / namespace rename used by the downstream consumer

If preferred, these can be split into separate PRs, but they are kept together here because the downstream implementation and validation were performed against the renamed package.

@bezysoftware
Copy link
Copy Markdown
Collaborator

Your changes touched 48 files, most of them unrelated, with a namespace update. Please revert those changes before I can review the rest

@canedha
Copy link
Copy Markdown
Author

canedha commented Mar 18, 2026 via email

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