Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Store timestamp and prepare GSI #7

Merged
merged 2 commits into from
May 29, 2024
Merged

feat: Store timestamp and prepare GSI #7

merged 2 commits into from
May 29, 2024

Conversation

patriknw
Copy link
Member

No description provided.


"Persist timestamp" should {

"be the same for events stored in same transaction" in {
Copy link
Member Author

Choose a reason for hiding this comment

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

This is what we have in r2dbc, but I think we could actually make it increasing by (at least) one micros per event. For r2dbc I think the only reason we use same timestamp is that the timestamp can (optionally) be created by the database.

Copy link
Member Author

Choose a reason for hiding this comment

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

changed this in 60aafab

previousNow.updateAndGet { prev =>
if (prev.isAfter(n)) prev.plus(1, ChronoUnit.MICROS)
else n
}
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm actually not sure if this is needed or if Instant.now() is safe enough. I wouldn't trust System.currentTimeMillis, which is used by the Instant system clock, but it's only used for the offset baseline and it's always 1024 seconds back in time. Question is if getNanoTimeAdjustment is monotonically increasing?

Copy link
Member Author

Choose a reason for hiding this comment

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

Independent of that, it's now needed.
The timestamp is now increasing by at least 1 micros, which is needed for the sorting of the by slice GSI. seqNr ordering and timestamp ordering should be the same.

The GSI is eventually consistent and may not preserve visibility order, but we handle that in other way. Having it in strict timestamp order will at least make the query return the items in the right order when the GSI has been populated.

Copy link
Contributor

Choose a reason for hiding this comment

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

👍🏼 Yes, sort keys will need to be unique.

Copy link
Member Author

@patriknw patriknw May 29, 2024

Choose a reason for hiding this comment

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

not for gsi, actually, for ordinary tables the primary key has to be unique. I'm sure I read that was not the case for gsi. We will not have unique timestamps anyway, because different Akka nodes can create the same timestamp.

Copy link
Contributor

Choose a reason for hiding this comment

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

Right, makes sense that index primary keys don't need to be unique. Could probably also have a composite sort key of timestamp and seq nr, if that's cleaner than needing the increasing timestamps.

* needed for sorting in the by slice GSI
Copy link
Contributor

@pvlugter pvlugter left a comment

Choose a reason for hiding this comment

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

LGTM

val slice = persistenceExt.sliceForPersistenceId(persistenceId)

def putItemAttributes(item: SerializedJournalItem) = {
import JournalAttributes._
val attributes = new JHashMap[String, AttributeValue]
attributes.put(Pid, AttributeValue.fromS(persistenceId))
attributes.put(SeqNr, AttributeValue.fromN(item.seqNr.toString))
attributes.put(Slice, AttributeValue.fromN(slice.toString))
attributes.put(EntityType, AttributeValue.fromS(item.entityType))
attributes.put(EntityTypeSlice, AttributeValue.fromS(s"$entityType-$slice"))
Copy link
Contributor

Choose a reason for hiding this comment

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

Simpler to have a single attribute for GSI partition key. Otherwise we could combine multiple attributes into the partition key if it's useful to have the slice attribute separate.

Copy link
Member Author

Choose a reason for hiding this comment

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

I thought it could only be one attribute for the partition key and one attribute for the sort key? Otherwise it would be better to use a partition key composed of entity type and slice attributes, for the gsi.

Copy link
Contributor

Choose a reason for hiding this comment

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

I thought composite keys was a thing. I can take another look.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, looks like only single attributes are possible and there's no composite key support.

@pvlugter pvlugter merged commit 6fe9e4f into main May 29, 2024
3 checks passed
@pvlugter pvlugter deleted the wip-gsi-patriknw branch May 29, 2024 04:36
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