diff --git a/internal/core/votes/interfaces.go b/internal/core/votes/interfaces.go index 7940d42..0c9e01a 100644 --- a/internal/core/votes/interfaces.go +++ b/internal/core/votes/interfaces.go @@ -2,30 +2,12 @@ package votes import "context" -// Service defines the business logic interface for votes -// Coordinates between Repository, user PDS, and vote validation -type Service interface { - // CreateVote creates a new vote or toggles an existing vote - // Flow: Validate -> Check existing vote -> Handle toggle logic -> Write to user's PDS -> Return URI/CID - // AppView indexing happens asynchronously via Jetstream consumer - // Toggle logic: - // - No vote -> Create vote - // - Same direction -> Delete vote (toggle off) - // - Different direction -> Delete old + Create new (toggle direction) - CreateVote(ctx context.Context, voterDID string, userAccessToken string, req CreateVoteRequest) (*CreateVoteResponse, error) - - // DeleteVote removes a vote from a post/comment - // Flow: Find vote -> Verify ownership -> Delete from user's PDS - // AppView decrements vote count asynchronously via Jetstream consumer - DeleteVote(ctx context.Context, voterDID string, userAccessToken string, req DeleteVoteRequest) error - - // GetVote retrieves a user's vote on a specific subject - // Used to check vote state before creating/toggling - GetVote(ctx context.Context, voterDID string, subjectURI string) (*Vote, error) -} - // Repository defines the data access interface for votes // Used by Jetstream consumer to index votes from firehose +// +// Architecture: Votes are written directly by clients to their PDS using +// com.atproto.repo.createRecord/deleteRecord. This AppView indexes votes +// from Jetstream for aggregation and querying. type Repository interface { // Create inserts a new vote into the AppView database // Called by Jetstream consumer after vote is created on PDS @@ -38,7 +20,7 @@ type Repository interface { // GetByVoterAndSubject retrieves a user's vote on a specific subject // Used to check existing vote state - GetByVoterAndSubject(ctx context.Context, voterDID string, subjectURI string) (*Vote, error) + GetByVoterAndSubject(ctx context.Context, voterDID, subjectURI string) (*Vote, error) // Delete soft-deletes a vote (sets deleted_at) // Called by Jetstream consumer after vote is deleted from PDS diff --git a/internal/core/votes/vote.go b/internal/core/votes/vote.go index 314aed6..c830ca9 100644 --- a/internal/core/votes/vote.go +++ b/internal/core/votes/vote.go @@ -7,47 +7,26 @@ import ( // Vote represents a vote in the AppView database // Votes are indexed from the firehose after being written to user repositories type Vote struct { - ID int64 `json:"id" db:"id"` + CreatedAt time.Time `json:"createdAt" db:"created_at"` + IndexedAt time.Time `json:"indexedAt" db:"indexed_at"` + DeletedAt *time.Time `json:"deletedAt,omitempty" db:"deleted_at"` URI string `json:"uri" db:"uri"` CID string `json:"cid" db:"cid"` RKey string `json:"rkey" db:"rkey"` VoterDID string `json:"voterDid" db:"voter_did"` SubjectURI string `json:"subjectUri" db:"subject_uri"` SubjectCID string `json:"subjectCid" db:"subject_cid"` - Direction string `json:"direction" db:"direction"` // "up" or "down" - CreatedAt time.Time `json:"createdAt" db:"created_at"` - IndexedAt time.Time `json:"indexedAt" db:"indexed_at"` - DeletedAt *time.Time `json:"deletedAt,omitempty" db:"deleted_at"` -} - -// CreateVoteRequest represents input for creating a new vote -// Matches social.coves.interaction.createVote lexicon input schema -type CreateVoteRequest struct { - Subject string `json:"subject"` // AT-URI of post/comment - Direction string `json:"direction"` // "up" or "down" -} - -// CreateVoteResponse represents the response from creating a vote -// Matches social.coves.interaction.createVote lexicon output schema -type CreateVoteResponse struct { - URI string `json:"uri"` // AT-URI of created vote record - CID string `json:"cid"` // CID of created vote record - Existing *string `json:"existing,omitempty"` // AT-URI of existing vote if updating -} - -// DeleteVoteRequest represents input for deleting a vote -// Matches social.coves.interaction.deleteVote lexicon input schema -type DeleteVoteRequest struct { - Subject string `json:"subject"` // AT-URI of post/comment + Direction string `json:"direction" db:"direction"` + ID int64 `json:"id" db:"id"` } -// VoteRecord represents the actual atProto record structure written to PDS +// VoteRecord represents the atProto record structure indexed from Jetstream // This is the data structure that gets stored in the user's repository type VoteRecord struct { - Type string `json:"$type"` - Subject StrongRef `json:"subject"` - Direction string `json:"direction"` // "up" or "down" - CreatedAt string `json:"createdAt"` + Type string `json:"$type"` + Subject StrongRef `json:"subject"` + Direction string `json:"direction"` // "up" or "down" + CreatedAt string `json:"createdAt"` } // StrongRef represents a strong reference to a record (URI + CID)