Skip to content

Fix the Server Timestamp README example, which does not compile - #849

Open
anggrayudi wants to merge 1 commit into
GitLiveApp:masterfrom
anggrayudi:docs/666-server-timestamp-readme
Open

Fix the Server Timestamp README example, which does not compile#849
anggrayudi wants to merge 1 commit into
GitLiveApp:masterfrom
anggrayudi:docs/666-server-timestamp-readme

Conversation

@anggrayudi

Copy link
Copy Markdown

Fixes #666.

Problem

The Server Timestamp example in the README cannot compile. @marcelpallares hit the first item below, and @mattegoghero followed up with "can't use the ServerTimestamp as written in the documentation" — the snippet is broken in five independent ways:

@Serializable
data class Post(
    // In case using Realtime Database.
    val timestamp = ServerValue.TIMESTAMP,
    // In case using Cloud Firestore.
    val timestamp: Timestamp = Timestamp.ServerTimestamp,
    // or
    val alternativeTimestamp = FieldValue.serverTimestamp,
    // or
    @Serializable(with = DoubleAsTimestampSerializer::class),
    val doubleTimestamp: Double = DoubleAsTimestampSerializer.serverTimestamp
)
  1. val timestamp: Timestamp = Timestamp.ServerTimestamp is a type error. ServerTimestamp is declared as data object ServerTimestamp : BaseTimestamp — it is not a Timestamp. The field has to be typed BaseTimestamp. This is the exact thing reported in the issue.
  2. timestamp is declared twice as a constructor parameter of the same class.
  3. val timestamp = ... and val alternativeTimestamp = ... omit their types, which constructor parameters may not do.
  4. The trailing comma after @Serializable(with = DoubleAsTimestampSerializer::class) is a syntax error.
  5. DoubleAsTimestampSerializer.serverTimestamp does not exist. The constant is DoubleAsTimestampSerializer.SERVER_TIMESTAMP.

Fix

Split the Realtime Database and Cloud Firestore cases into separate snippets — the original folded both into one class, which is where the duplicated field name came from — and correct the types and the constant name. I also added a short note on why the Firestore field is a BaseTimestamp, since that is the part that surprises people.

Every symbol in the new snippets is checked against the source rather than assumed:

  • ServerValue.TIMESTAMP: ServerValue, and ServerValue is @Serializable(with = ServerValueSerializer::class)
  • Timestamp.ServerTimestamp : BaseTimestamp, and BaseTimestamp is @Serializable(with = BaseTimestampSerializer::class)
  • FieldValue.serverTimestamp: FieldValue, and FieldValue is @Serializable(with = FieldValueSerializer::class)
  • DoubleAsTimestampSerializer.SERVER_TIMESTAMP: Double

Scope — the second half of the issue is not addressed here

The issue also reports a runtime failure when writing a ServerTimestamp:

java.lang.RuntimeException: No properties to serialize found on class dev.gitlive.firebase.firestore.Timestamp$ServerTimestamp

I deliberately did not touch that, because I could not reproduce it and the encoding path looks correct:

  • BaseTimestampSerializer.toNativeValue maps Timestamp.ServerTimestamp to FieldValue.serverTimestamp.nativeValue
  • TimestampTests.serializers() already asserts that (Timestamp.ServerTimestamp as BaseTimestamp).firebaseSerializer() resolves to BaseTimestampSerializer, and it has done so since April 2023 — before this issue was filed
  • DocumentReferenceTest.testServerTimestampFieldValue writes a ServerTimestamp end to end
  • the platform set now takes an already-encoded EncodedObject, so the native SDK never sees an unencoded Kotlin value

The stack trace shows Google's CustomClassMapper reflecting over the GitLive object, i.e. it arrived at the Android SDK unencoded, which is what @Daeda88 suspected. That points at either an older version or a call path that bypasses the GitLive encoder. Since @marcelpallares never came back on @Daeda88's questions, there is nothing further to go on — so this PR fixes only the documentation defect, which is real, verifiable, and is what both reporters actually ran into.

The Server Timestamp snippet could not compile, in five separate ways:

- `val timestamp: Timestamp = Timestamp.ServerTimestamp` is a type error.
  `ServerTimestamp` is declared as `data object ServerTimestamp : BaseTimestamp`,
  so the field has to be typed `BaseTimestamp`. This is what people actually
  hit when following the docs.
- `timestamp` was declared twice as a constructor parameter of the same class.
- `val timestamp = ServerValue.TIMESTAMP` and
  `val alternativeTimestamp = FieldValue.serverTimestamp` omit the type, which
  constructor parameters may not do.
- a trailing comma after `@Serializable(with = DoubleAsTimestampSerializer::class)`
  is a syntax error.
- `DoubleAsTimestampSerializer.serverTimestamp` does not exist; the constant is
  `DoubleAsTimestampSerializer.SERVER_TIMESTAMP`.

Split the Realtime Database and Cloud Firestore cases into separate snippets,
since the original combined them into one class with a duplicated field name,
and note why the Firestore field is a `BaseTimestamp`.

Fixes GitLiveApp#666
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.

[Issue] ServerTimestamp not working

1 participant