Skip to content

Commit 99eefad

Browse files
committed
[raft/scd] Add scd Raftstore subscriptions
1 parent cc5f201 commit 99eefad

4 files changed

Lines changed: 564 additions & 23 deletions

File tree

pkg/scd/store/raftstore/store.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,20 @@ const (
3232
GetOperationalIntentTransaction raftstore.RequestType = "getOperationalIntentTransaction"
3333
QueryOperationalIntentTransaction raftstore.RequestType = "queryOperationalIntentTransaction"
3434
UpsertOperationalIntentTransaction raftstore.RequestType = "upsertOperationalIntentTransaction"
35+
36+
searchSubscriptions raftstore.RequestType = "searchSubscriptions"
37+
getSubscription raftstore.RequestType = "getSubscription"
38+
upsertSubscription raftstore.RequestType = "upsertSubscription"
39+
deleteSubscription raftstore.RequestType = "deleteSubscription"
40+
incrementNotificationForOIs raftstore.RequestType = "incrementNotificationForOIs"
41+
incrementNotificationForConstraints raftstore.RequestType = "incrementNotificationForConstraints"
42+
listExpiredSubscriptions raftstore.RequestType = "listExpiredSubscriptions"
43+
countSubscriptions raftstore.RequestType = "countSubscriptions"
44+
45+
DeleteSubscriptionTransaction raftstore.RequestType = "deleteSubscriptionTransaction"
46+
GetSubscriptionTransaction raftstore.RequestType = "getSubscriptionTransaction"
47+
QuerySubscriptionTransaction raftstore.RequestType = "querySubscriptionTransaction"
48+
UpsertSubscriptionTransaction raftstore.RequestType = "upsertSubscriptionTransaction"
3549
)
3650

3751
var readOnlyRequests = []raftstore.RequestType{
@@ -43,6 +57,14 @@ var readOnlyRequests = []raftstore.RequestType{
4357

4458
GetOperationalIntentTransaction,
4559
QueryOperationalIntentTransaction,
60+
61+
searchSubscriptions,
62+
getSubscription,
63+
listExpiredSubscriptions,
64+
countSubscriptions,
65+
66+
GetSubscriptionTransaction,
67+
QuerySubscriptionTransaction,
4668
}
4769

4870
// repo is a full implementation of scd.repos.Repository for Raft-based storage.
@@ -158,6 +180,77 @@ func (r *repo) Apply(ctx context.Context, proposal consensus.Proposal) (any, err
158180
case UpsertOperationalIntentTransaction:
159181
return r.upsertOperationalIntentTransactionApplier(ctx, proposal, mem)
160182

183+
case searchSubscriptions:
184+
var v4d *dssmodels.Volume4D
185+
if err := json.Unmarshal(proposal.Value, &v4d); err != nil {
186+
return nil, stacktrace.Propagate(err, "failed to unmarshal %s proposal value", searchSubscriptions)
187+
}
188+
189+
return mem.SearchSubscriptions(ctx, v4d)
190+
191+
case getSubscription:
192+
var id dssmodels.ID
193+
if err := json.Unmarshal(proposal.Value, &id); err != nil {
194+
return nil, stacktrace.Propagate(err, "failed to unmarshal %s proposal value", getSubscription)
195+
}
196+
197+
return mem.GetSubscription(ctx, id)
198+
199+
case upsertSubscription:
200+
var sub *scdmodels.Subscription
201+
if err := json.Unmarshal(proposal.Value, &sub); err != nil {
202+
return nil, stacktrace.Propagate(err, "failed to unmarshal %s proposal value", upsertSubscription)
203+
}
204+
205+
return mem.UpsertSubscription(ctx, sub)
206+
207+
case deleteSubscription:
208+
var id dssmodels.ID
209+
if err := json.Unmarshal(proposal.Value, &id); err != nil {
210+
return nil, stacktrace.Propagate(err, "failed to unmarshal %s proposal value", deleteSubscription)
211+
}
212+
213+
return nil, mem.DeleteSubscription(ctx, id)
214+
215+
case incrementNotificationForOIs:
216+
var v4d *dssmodels.Volume4D
217+
if err := json.Unmarshal(proposal.Value, &v4d); err != nil {
218+
return nil, stacktrace.Propagate(err, "failed to unmarshal %s proposal value", incrementNotificationForOIs)
219+
}
220+
221+
return mem.IncrementNotificationIndicesForOperationalIntents(ctx, v4d)
222+
223+
case incrementNotificationForConstraints:
224+
var v4d *dssmodels.Volume4D
225+
if err := json.Unmarshal(proposal.Value, &v4d); err != nil {
226+
return nil, stacktrace.Propagate(err, "failed to unmarshal %s proposal value", incrementNotificationForConstraints)
227+
}
228+
229+
return mem.IncrementNotificationIndicesForConstraints(ctx, v4d)
230+
231+
case listExpiredSubscriptions:
232+
var threshold time.Time
233+
if err := json.Unmarshal(proposal.Value, &threshold); err != nil {
234+
return nil, stacktrace.Propagate(err, "failed to unmarshal %s proposal value", listExpiredSubscriptions)
235+
}
236+
237+
return mem.ListExpiredSubscriptions(ctx, threshold)
238+
239+
case countSubscriptions:
240+
return mem.CountSubscriptions(ctx)
241+
242+
case UpsertSubscriptionTransaction:
243+
return r.upsertSubscriptionTransactionApplier(ctx, proposal, mem)
244+
245+
case DeleteSubscriptionTransaction:
246+
return r.deleteSubscriptionTransactionApplier(ctx, proposal, mem)
247+
248+
case GetSubscriptionTransaction:
249+
return r.getSubscriptionTransactionApplier(ctx, proposal, mem)
250+
251+
case QuerySubscriptionTransaction:
252+
return r.querySubscriptionTransactionApplier(ctx, proposal, mem)
253+
161254
default:
162255
return nil, stacktrace.NewError("unknown request type: %q", proposal.RequestType)
163256
}

pkg/scd/store/raftstore/subscriptions.go

Lines changed: 118 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,44 +5,143 @@ import (
55
"time"
66

77
"github.com/golang/geo/s2"
8-
dsserr "github.com/interuss/dss/pkg/errors"
98
dssmodels "github.com/interuss/dss/pkg/models"
109
scdmodels "github.com/interuss/dss/pkg/scd/models"
1110
"github.com/interuss/stacktrace"
1211
)
1312

14-
func (r *repo) SearchSubscriptions(_ context.Context, v4d *dssmodels.Volume4D) ([]*scdmodels.Subscription, error) {
15-
return nil, stacktrace.NewErrorWithCode(dsserr.NotImplemented, "SearchSubscriptions not implemented for raftstore")
13+
func (r *repo) SearchSubscriptions(ctx context.Context, v4d *dssmodels.Volume4D) ([]*scdmodels.Subscription, error) {
14+
result, err := r.consensus.ProposeValue(ctx, storeID, string(searchSubscriptions), v4d, true)
15+
if err != nil {
16+
return nil, stacktrace.Propagate(err, "failed to propose searchSubscriptions")
17+
}
18+
19+
if result == nil {
20+
return nil, nil
21+
}
22+
23+
subs, ok := result.([]*scdmodels.Subscription)
24+
if !ok {
25+
return nil, stacktrace.NewError("invalid result type: %T", result)
26+
}
27+
28+
return subs, nil
1629
}
1730

18-
func (r *repo) GetSubscription(_ context.Context, id dssmodels.ID) (*scdmodels.Subscription, error) {
19-
return nil, stacktrace.NewErrorWithCode(dsserr.NotImplemented, "GetSubscription not implemented for raftstore")
31+
func (r *repo) GetSubscription(ctx context.Context, id dssmodels.ID) (*scdmodels.Subscription, error) {
32+
result, err := r.consensus.ProposeValue(ctx, storeID, string(getSubscription), id, true)
33+
if err != nil {
34+
return nil, stacktrace.Propagate(err, "failed to propose getSubscription")
35+
}
36+
37+
if result == nil {
38+
return nil, nil
39+
}
40+
41+
sub, ok := result.(*scdmodels.Subscription)
42+
if !ok {
43+
return nil, stacktrace.NewError("invalid result type: %T", result)
44+
}
45+
46+
return sub, nil
2047
}
2148

22-
func (r *repo) UpsertSubscription(_ context.Context, sub *scdmodels.Subscription) (*scdmodels.Subscription, error) {
23-
return nil, stacktrace.NewErrorWithCode(dsserr.NotImplemented, "UpsertSubscription not implemented for raftstore")
49+
func (r *repo) UpsertSubscription(ctx context.Context, sub *scdmodels.Subscription) (*scdmodels.Subscription, error) {
50+
result, err := r.consensus.ProposeValue(ctx, storeID, string(upsertSubscription), sub, false)
51+
if err != nil {
52+
return nil, stacktrace.Propagate(err, "failed to propose upsertSubscription")
53+
}
54+
55+
if result == nil {
56+
return nil, nil
57+
}
58+
59+
upserted, ok := result.(*scdmodels.Subscription)
60+
if !ok {
61+
return nil, stacktrace.NewError("invalid result type: %T", result)
62+
}
63+
64+
return upserted, nil
2465
}
2566

26-
func (r *repo) DeleteSubscription(_ context.Context, id dssmodels.ID) error {
27-
return stacktrace.NewErrorWithCode(dsserr.NotImplemented, "DeleteSubscription not implemented for raftstore")
67+
func (r *repo) DeleteSubscription(ctx context.Context, id dssmodels.ID) error {
68+
_, err := r.consensus.ProposeValue(ctx, storeID, string(deleteSubscription), id, false)
69+
return err
2870
}
2971

30-
func (r *repo) IncrementNotificationIndicesForOperationalIntents(_ context.Context, v4d *dssmodels.Volume4D) ([]*scdmodels.Subscription, error) {
31-
return nil, stacktrace.NewErrorWithCode(dsserr.NotImplemented, "IncrementNotificationIndicesForOperationalIntents not implemented for raftstore")
72+
func (r *repo) IncrementNotificationIndicesForOperationalIntents(ctx context.Context, v4d *dssmodels.Volume4D) ([]*scdmodels.Subscription, error) {
73+
result, err := r.consensus.ProposeValue(ctx, storeID, string(incrementNotificationForOIs), v4d, false)
74+
if err != nil {
75+
return nil, stacktrace.Propagate(err, "failed to propose incrementNotificationForOIs")
76+
}
77+
78+
if result == nil {
79+
return nil, nil
80+
}
81+
82+
subs, ok := result.([]*scdmodels.Subscription)
83+
if !ok {
84+
return nil, stacktrace.NewError("invalid result type: %T", result)
85+
}
86+
87+
return subs, nil
3288
}
3389

34-
func (r *repo) IncrementNotificationIndicesForConstraints(_ context.Context, v4d *dssmodels.Volume4D) ([]*scdmodels.Subscription, error) {
35-
return nil, stacktrace.NewErrorWithCode(dsserr.NotImplemented, "IncrementNotificationIndicesForConstraints not implemented for raftstore")
90+
func (r *repo) IncrementNotificationIndicesForConstraints(ctx context.Context, v4d *dssmodels.Volume4D) ([]*scdmodels.Subscription, error) {
91+
result, err := r.consensus.ProposeValue(ctx, storeID, string(incrementNotificationForConstraints), v4d, false)
92+
if err != nil {
93+
return nil, stacktrace.Propagate(err, "failed to propose incrementNotificationForConstraints")
94+
}
95+
96+
if result == nil {
97+
return nil, nil
98+
}
99+
100+
subs, ok := result.([]*scdmodels.Subscription)
101+
if !ok {
102+
return nil, stacktrace.NewError("invalid result type: %T", result)
103+
}
104+
105+
return subs, nil
36106
}
37107

38-
func (r *repo) LockSubscriptionsOnCells(_ context.Context, cells s2.CellUnion, subscriptionIds []dssmodels.ID, startTime *time.Time, endTime *time.Time) error {
39-
return stacktrace.NewErrorWithCode(dsserr.NotImplemented, "LockSubscriptionsOnCells not implemented for raftstore")
108+
func (r *repo) LockSubscriptionsOnCells(_ context.Context, _ s2.CellUnion, _ []dssmodels.ID, _ *time.Time, _ *time.Time) error {
109+
// for the raftstore, LockSubscriptionsOnCells is a no-op
110+
return nil
40111
}
41112

42-
func (r *repo) ListExpiredSubscriptions(_ context.Context, threshold time.Time) ([]*scdmodels.Subscription, error) {
43-
return nil, stacktrace.NewErrorWithCode(dsserr.NotImplemented, "ListExpiredSubscriptions not implemented for raftstore")
113+
func (r *repo) ListExpiredSubscriptions(ctx context.Context, threshold time.Time) ([]*scdmodels.Subscription, error) {
114+
result, err := r.consensus.ProposeValue(ctx, storeID, string(listExpiredSubscriptions), threshold, true)
115+
if err != nil {
116+
return nil, stacktrace.Propagate(err, "failed to propose listExpiredSubscriptions")
117+
}
118+
119+
if result == nil {
120+
return nil, nil
121+
}
122+
123+
subs, ok := result.([]*scdmodels.Subscription)
124+
if !ok {
125+
return nil, stacktrace.NewError("invalid result type: %T", result)
126+
}
127+
128+
return subs, nil
44129
}
45130

46-
func (r *repo) CountSubscriptions(_ context.Context) (int64, error) {
47-
return 0, stacktrace.NewErrorWithCode(dsserr.NotImplemented, "CountSubscriptions not implemented for raftstore")
131+
func (r *repo) CountSubscriptions(ctx context.Context) (int64, error) {
132+
result, err := r.consensus.ProposeValue(ctx, storeID, string(countSubscriptions), nil, true)
133+
if err != nil {
134+
return 0, stacktrace.Propagate(err, "failed to propose countSubscriptions")
135+
}
136+
137+
if result == nil {
138+
return 0, nil
139+
}
140+
141+
count, ok := result.(int64)
142+
if !ok {
143+
return 0, stacktrace.NewError("invalid result type: %T", result)
144+
}
145+
146+
return count, nil
48147
}

0 commit comments

Comments
 (0)