tinyrelayfile
tinyrelay/internal/daemon/event_commit.go/

internal/daemon/event_commit.go raw
1package daemon
2
3import (
4 "context"
5 "database/sql"
6 "encoding/json"
7
8 "github.com/FelineStateMachine/tinyrelay/internal/community"
9 "github.com/FelineStateMachine/tinyrelay/internal/event"
10 gitrelay "github.com/FelineStateMachine/tinyrelay/tinygit"
11 "github.com/FelineStateMachine/tinyrelay/internal/policy"
12 "github.com/FelineStateMachine/tinyrelay/internal/replication"
13 "github.com/FelineStateMachine/tinyrelay/internal/sites"
14 "github.com/FelineStateMachine/tinyrelay/internal/storage"
15)
16
17// eventCommitter prepares the projections common to client publication and
18// replication. Admission and client-only protocol actions remain with their
19// entry points; every projection here participates in the event transaction.
20type eventCommitter struct {
21 policy policy.Policy
22 community *community.Service
23 sites *sites.Service
24 git *gitrelay.GitRelay
25}
26
27type eventCommitPlan struct {
28 options storage.SaveOptions
29 repository gitrelay.Repository
30 gitMetadata bool
31 followups *storage.Intent
32}
33
34func (c eventCommitter) prepare(ctx context.Context, e event.Event, origin replication.Origin, now int64) (eventCommitPlan, error) {
35 plan := eventCommitPlan{options: storage.SaveOptions{Now: now}}
36 if c.sites != nil {
37 plan.options = c.sites.SaveOptions(e, now)
38 }
39 plan.options.SearchMode = c.policy.Features.Search
40 if e.Kind == 30023 {
41 plan.options.Intents = append(plan.options.Intents, storage.Intent{Kind: "view-publish", EventID: e.ID, Target: "articles", Payload: "{}"})
42 }
43 if e.Kind == event.KIND_AGENT_GRANT || e.Kind == event.KIND_DELETION {
44 plan.options.AddBeforeCommit(func(ctx context.Context, tx *sql.Tx) error {
45 return c.community.ApplyAgentEventTx(ctx, tx, e, now)
46 })
47 }
48 if c.policy.Features.Grasp && (e.Kind == event.KIND_REPO || e.Kind == event.KIND_REPO_STATE) {
49 if err := c.prepareRepository(ctx, e, origin, &plan); err != nil {
50 return eventCommitPlan{}, err
51 }
52 }
53 return plan, nil
54}
55
56func (c eventCommitter) prepareRepository(ctx context.Context, e event.Event, origin replication.Origin, plan *eventCommitPlan) error {
57 validate := c.git.ValidateImported
58 if origin == replication.OriginClient {
59 validate = c.git.Validate
60 }
61 repo, err := validate(ctx, e)
62 if err != nil {
63 return err
64 }
65 raw, err := json.Marshal(repo)
66 if err != nil {
67 return err
68 }
69 plan.repository, plan.gitMetadata = repo, true
70 plan.options.Intents = append(plan.options.Intents, storage.Intent{Kind: "git-metadata", EventID: e.ID, Target: repo.Owner + ":" + repo.Identifier, Payload: string(raw)})
71 if e.Kind == event.KIND_REPO_STATE {
72 plan.options.AddBeforeCommit(func(ctx context.Context, tx *sql.Tx) error {
73 _, err := tx.ExecContext(ctx, "INSERT OR REPLACE INTO pending_events(id,reason) VALUES(?,'git objects')", e.ID)
74 return err
75 })
76 }
77 return nil
78}
79
80func (t *Tenant) validateStoredEvent(ctx context.Context, e event.Event) error {
81 if err := t.validatePrivateRepositoryPlacement(ctx, e); err != nil {
82 return err
83 }
84 if err := validateReviewAnchor(e); err != nil {
85 return err
86 }
87 if t.sites != nil {
88 return sites.ValidateManifest(e)
89 }
90 return nil
91}
92
93func (t *Tenant) prepareStoredEvent(ctx context.Context, e event.Event, origin replication.Origin, now int64) (eventCommitPlan, error) {
94 committer := eventCommitter{policy: t.Policy(), community: t.community, sites: t.sites, git: t.git}
95 plan, err := committer.prepare(ctx, e, origin, now)
96 if err != nil {
97 return plan, err
98 }
99 var push *replicationPushFollowupPayload
100 if origin == replication.OriginClient && t.Policy().Features.Push {
101 payload, _ := t.prepareReplicationPushFollowup(ctx, e, now)
102 if len(payload.RegistrationIDs) != 0 || payload.Discover {
103 push = &payload
104 }
105 }
106 plan.followups = t.followups.prepareWithPush(ctx, e, now, false, push)
107 if plan.followups != nil {
108 plan.options.Intents = append(plan.options.Intents, *plan.followups)
109 }
110 return plan, nil
111}
112
113func (t *Tenant) afterStoredEvent(ctx context.Context, e event.Event, followups *storage.Intent) {
114 t.notifyDevices(ctx, e)
115 t.followups.try(ctx, followups)
116 if event.IsEphemeral(e.Kind) {
117 t.notifyCallbacks(ctx, e)
118 }
119 t.customViews.cascadeViewDeletion(ctx, e)
120 t.notifyWikiMerge(ctx, e)
121 t.notifyWikiProposal(ctx, e)
122}

About

ownerc01503e8035f
visibilitypublic
headd730679639bf

Maintainers

  • c01503e8035f owner
  • ba1b5beed5b5 agent hermes

Clone

  • https://012.run/npub1cq2s86qrtadf36eqq3epm38wmhdynrrcwxf84eldk3f94dkv7ttsrulrz5/tinyrelay.git

Refs