Skip to content

added presence api update#1489

Open
ArnabChatterjee20k wants to merge 6 commits intomasterfrom
presence-api
Open

added presence api update#1489
ArnabChatterjee20k wants to merge 6 commits intomasterfrom
presence-api

Conversation

@ArnabChatterjee20k
Copy link
Copy Markdown
Member

What does this PR do?

(Provide a description of what this PR does.)

Test Plan

(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work.)

Related PRs and Issues

(If this PR is related to any other PR or resolves any issue or related to any issue link all related PR and issues here.)

Have you read the Contributing Guidelines on issues?

(Write your answer here.)

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 29, 2026

Greptile Summary

This PR adds a createPresence API to the Realtime service across all SDK templates (Web, Flutter, Android, Apple/Swift, Kotlin), refactors the mock server to use utopia-php/websocket with a proper WebSocket protocol handler, and makes the additionalProperties field name configurable via the x-additional-properties-key OpenAPI extension across all model templates.

  • Presence API: createPresence is added to all realtime templates using a FIFO pendingPresenceRequests queue correlated to server responses. handleError / handleResponseError correctly drain the queue on server-side error frames, but connection-level close and disconnect() paths still do not drain the queue on several platforms (previously raised).
  • Configurable additionalPropertiesKey: All model templates (Dart, Kotlin, Android, Swift, PHP, Python, Ruby, Rust, C#) are updated to use the new key — correctly for all languages except Swift, where the CodingKeys enum case is missing its explicit raw-string value, which would break Codable for any $-prefixed key name.
  • Mock server refactor: The Swoole HTTP server is replaced with the utopia-php/websocket abstraction and a new Protocol/Connection class pair implements the full realtime message contract needed by the test fixtures.

Confidence Score: 3/5

The presence API implementation has multiple platform-specific gaps where in-flight requests are never settled on connection drop, and a template bug in the Swift model generator produces broken Codable conformance for any schema using a dollar-sign-prefixed additionalPropertiesKey.

The Swift model template omits the raw-string value on the new CodingKeys case, meaning any dollar-sign-prefixed x-additional-properties-key generates Swift code that silently reads/writes the wrong JSON field. Across Flutter, Web, and Android realtime templates, the onDone/onError/close/disconnect paths do not drain pendingPresenceRequests, so any createPresence call in flight when the connection drops will hang indefinitely.

templates/swift/Sources/Models/Model.swift.twig (CodingKeys raw value), templates/flutter/lib/src/realtime_mixin.dart.twig, templates/web/src/services/realtime.ts.twig, and templates/android/library/src/main/java/io/package/services/Realtime.kt.twig (connection-close drain gaps)

Important Files Changed

Filename Overview
templates/swift/Sources/Models/Model.swift.twig Adds additionalPropertiesKey support but the new CodingKeys enum case is missing its raw string value, which breaks Codable for any key that diverges from the Swift identifier (e.g., $-prefixed keys).
mock-server/src/Utopia/Realtime/Protocol.php New Protocol class cleanly implements the realtime WebSocket mock; presence handler returns a shaped response matching what SDK tests expect.
mock-server/src/Utopia/Realtime/Connection.php Simple per-connection state container; no issues.
mock-server/app/http.php Migrates from raw Swoole to utopia-php/websocket abstraction and wires up the new RealtimeProtocol WebSocket handlers; looks correct.
src/Spec/Swagger2.php Adds additionalPropertiesKey by reading x-additional-properties-key from the spec, defaulting to data for backward compatibility.
templates/web/src/services/realtime.ts.twig Adds createPresence with a FIFO pending-request queue; handleError now drains it, but the socket close event handler and disconnect() do not drain pendingPresenceRequests, leaving in-flight presence calls permanently unresolved on unexpected close or explicit disconnect.
templates/flutter/lib/src/realtime_mixin.dart.twig Adds createPresenceTo and drains _pendingPresenceRequests in handleError, but the onDone and onError stream callbacks do not drain the queue, so a connection drop leaves presence completers permanently uncompleted.
templates/android/library/src/main/java/io/package/services/Realtime.kt.twig Adds createPresence with a FIFO deferred queue; handleResponseError drains it, but onClosing/onFailure callbacks do not, leaving in-flight calls hanging on socket close.
templates/apple/Sources/Services/Realtime.swift.twig Adds createPresence using CheckedContinuation; handleResponseError drains the pending queue, but onClose and onError delegate callbacks do not, causing continuation leaks on connection drop.
templates/dart/lib/src/models/model.dart.twig Correctly substitutes data with additionalPropertiesKey throughout; no issues.
templates/kotlin/src/main/kotlin/io/appwrite/models/Model.kt.twig Correctly substitutes data with additionalPropertiesKey in all serialized name annotations and fromMap/toMap helpers; no issues.
templates/android/library/src/main/java/io/package/models/Model.kt.twig Same additionalPropertiesKey substitution as the Kotlin template; no issues.
templates/dotnet/Package/Models/Model.cs.twig Correctly applies caseUcfirst/caseCamel transformations for the C# property and constructor parameter; no issues.
templates/php/src/Models/Model.php.twig Uses caseCamel for the PHP property name; no issues.
templates/python/package/models/model.py.twig Uses caseSnake for the private attribute and property accessors; no issues.
templates/ruby/lib/container/models/model.rb.twig Uses caseSnake for the Ruby accessor and initializer parameter; no issues.
templates/rust/src/models/model.rs.twig Uses caseSnake for the Rust field name; #[serde(flatten)] means serde handles the actual JSON key independently, so no key-mismatch risk here.
tests/languages/flutter/tests.dart Presence test calls subscribe without awaiting socket open, then immediately calls createPresence; the WebSocket factory is deferred via Future.delayed(Duration.zero), so _websok is still null when createPresenceTo runs and the test always falls into the catch block.
tests/languages/web/index.html Presence test follows the same await subscribecreatePresence pattern used by existing realtime tests; consistent with prior test structure.
tests/languages/android/Tests.kt Presence test wires up a fresh client and subscribes before calling createPresence; same approach as existing realtime tests in this file.
tests/languages/apple/Tests.swift Presence test properly awaits subscribe before calling createPresence, consistent with the Swift async/await pattern.

Reviews (4): Last reviewed commit: "updated mock server" | Re-trigger Greptile


return completer.future;
}
} No newline at end of file
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing newline at end of file

The file no longer ends with a newline. Most linters and git tools flag this; adding a trailing newline keeps the file consistent with the rest of the codebase.

{%~ endfor %}
{%~ if definition.additionalProperties %}
case data
case {{ definition.additionalPropertiesKey | default('data') | escapeSwiftKeyword | removeDollarSign }}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 The CodingKeys enum case for additionalPropertiesKey is missing its explicit raw-string value. All regular properties use case <identifier> = "<json-key>" so that the Swift identifier (after removeDollarSign) stays bound to the correct JSON key even when the names diverge. The new additionalProperties case omits the = "..." part, so Swift falls back to using the identifier name as the key. If additionalPropertiesKey is anything that requires escaping (e.g., a $-prefixed key like $presence), removeDollarSign strips the $ and the generated Codable conformance will silently read/write the wrong JSON field.

Suggested change
case {{ definition.additionalPropertiesKey | default('data') | escapeSwiftKeyword | removeDollarSign }}
case {{ definition.additionalPropertiesKey | default('data') | escapeSwiftKeyword | removeDollarSign }} = "{{ definition.additionalPropertiesKey | default('data') }}"

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.

1 participant