feat: presence on tickets

A ticket's page beats every 10 s (touchPresence / PUT
/issues/{issue}/presence, with whether I am editing) and gets back who
else is there, editing ones first. Entries live in Redis, one hash per
ticket, and fade after 30 s without a beat; leaving the page takes me out
at once. Only for people who can read the ticket; never in the event
store. The ticket shows «Bob está editando · Ana también lo está viendo»
above its title; editing means a ticket or comment form is open or a
comment is being written.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-15 16:53:47 +02:00
parent 869acd3f1f
commit f60d4c8346
33 changed files with 1197 additions and 22 deletions

View File

@@ -871,6 +871,9 @@ type Mutation {
duplicateIssue(issueId: ID!): CommandResult!
editComment(body: String!, commentId: ID!): CommandResult!
"""I left this ticket's page"""
leavePresence(issueId: ID!): Boolean!
"""Relate tickets, e.g. FE DEPENDS_ON BE, QA TESTS FE"""
linkIssues(input: LinkIssuesInput!): CommandResult!
@@ -933,6 +936,11 @@ type Mutation {
"""Send a ping now and tell how it went"""
testWebhook(webhookId: ID!): WebhookDelivery!
"""
I am on this ticket (send every ~10 s while the page is open): answers who else is, the ones editing first
"""
touchPresence(editing: Boolean! = false, issueId: ID!): [Presence!]!
"""
To the trash (whoever opened it, or an owner/admin): hidden everywhere, deleted for good after 30 days
"""
@@ -1074,6 +1082,16 @@ type OptionCount {
value: String!
}
"""Someone on a ticket right now (heartbeat in the last 30 s)"""
type Presence {
"""Last heartbeat"""
at: String!
"""Editing the ticket or writing a comment"""
editing: Boolean!
user: UserRef!
}
type PriorityCount {
count: Int!
priority: IssuePriority!