Skip to content

Commit a73b194

Browse files
authored
Add priority to app providers (#2263)
1 parent 7d11450 commit a73b194

File tree

4 files changed

+453
-68
lines changed

4 files changed

+453
-68
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Enhancement: Add priority to app providers
2+
3+
Before the order of the list returned by the method FindProviders
4+
of app providers depended from the order in which the app provider registered
5+
themselves.
6+
Now, it is possible to specify a priority for each app provider, and even if
7+
an app provider re-register itself (for example after a restart), the order
8+
is kept.
9+
10+
https://github.com/cs3org/reva/pull/2230
11+
https://github.com/cs3org/cs3apis/pull/157
12+
https://github.com/cs3org/reva/pull/2263

internal/grpc/services/appprovider/appprovider.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ import (
2222
"context"
2323
"errors"
2424
"os"
25+
"strconv"
2526
"time"
2627

2728
providerpb "github.com/cs3org/go-cs3apis/cs3/app/provider/v1beta1"
2829
registrypb "github.com/cs3org/go-cs3apis/cs3/app/registry/v1beta1"
2930
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
31+
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
3032
"github.com/cs3org/reva/pkg/app"
3133
"github.com/cs3org/reva/pkg/app/provider/registry"
3234
"github.com/cs3org/reva/pkg/errtypes"
@@ -55,6 +57,7 @@ type config struct {
5557
AppProviderURL string `mapstructure:"app_provider_url"`
5658
GatewaySvc string `mapstructure:"gatewaysvc"`
5759
MimeTypes []string `mapstructure:"mime_types"`
60+
Priority uint64 `mapstructure:"priority"`
5861
}
5962

6063
func (c *config) init() {
@@ -122,7 +125,20 @@ func (s *service) registerProvider() {
122125
log.Error().Err(err).Msgf("error registering app provider: could not get gateway client")
123126
return
124127
}
125-
res, err := client.AddAppProvider(ctx, &registrypb.AddAppProviderRequest{Provider: pInfo})
128+
req := &registrypb.AddAppProviderRequest{Provider: pInfo}
129+
130+
if s.conf.Priority != 0 {
131+
req.Opaque = &types.Opaque{
132+
Map: map[string]*types.OpaqueEntry{
133+
"priority": {
134+
Decoder: "plain",
135+
Value: []byte(strconv.FormatUint(s.conf.Priority, 10)),
136+
},
137+
},
138+
}
139+
}
140+
141+
res, err := client.AddAppProvider(ctx, req)
126142
if err != nil {
127143
log.Error().Err(err).Msgf("error registering app provider: error calling add app provider")
128144
return

pkg/app/registry/static/static.go

Lines changed: 71 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
package static
2020

2121
import (
22+
"container/heap"
2223
"context"
2324
"fmt"
25+
"strconv"
2426
"strings"
2527
"sync"
2628

@@ -37,6 +39,8 @@ func init() {
3739
registry.Register("static", New)
3840
}
3941

42+
const defaultPriority = 0
43+
4044
type mimeTypeConfig struct {
4145
MimeType string `mapstructure:"mime_type"`
4246
Extension string `mapstructure:"extension"`
@@ -45,9 +49,7 @@ type mimeTypeConfig struct {
4549
Icon string `mapstructure:"icon"`
4650
DefaultApp string `mapstructure:"default_app"`
4751
AllowCreation bool `mapstructure:"allow_creation"`
48-
// apps keeps the Providers able to open this mime type.
49-
// the list will always keep the default AppProvider at the head
50-
apps []*registrypb.ProviderInfo
52+
apps providerHeap
5153
}
5254

5355
type config struct {
@@ -122,7 +124,7 @@ func New(m map[string]interface{}) (app.Registry, error) {
122124
func unregisterProvider(p *registrypb.ProviderInfo, mime *mimeTypeConfig) {
123125
if index, in := getIndex(mime.apps, p); in {
124126
// remove the provider from the list
125-
mime.apps = append(mime.apps[:index], mime.apps[index+1:]...)
127+
heap.Remove(&mime.apps, index)
126128
}
127129
}
128130

@@ -131,11 +133,21 @@ func registerProvider(p *registrypb.ProviderInfo, mime *mimeTypeConfig) {
131133
// so we will remove it
132134
unregisterProvider(p, mime)
133135

134-
if providerIsDefaultForMimeType(p, mime) {
135-
mime.apps = prependProvider(p, mime.apps)
136-
} else {
137-
mime.apps = append(mime.apps, p)
136+
heap.Push(&mime.apps, providerWithPriority{
137+
provider: p,
138+
priority: getPriority(p),
139+
})
140+
}
141+
142+
func getPriority(p *registrypb.ProviderInfo) uint64 {
143+
if p.Opaque != nil && len(p.Opaque.Map) != 0 {
144+
if priority, ok := p.Opaque.Map["priority"]; ok {
145+
if pr, err := strconv.ParseUint(string(priority.GetValue()), 10, 64); err == nil {
146+
return pr
147+
}
148+
}
138149
}
150+
return defaultPriority
139151
}
140152

141153
func (m *manager) FindProviders(ctx context.Context, mimeType string) ([]*registrypb.ProviderInfo, error) {
@@ -160,15 +172,11 @@ func (m *manager) FindProviders(ctx context.Context, mimeType string) ([]*regist
160172
mimeMatch := mimeInterface.(*mimeTypeConfig)
161173
var providers = make([]*registrypb.ProviderInfo, 0, len(mimeMatch.apps))
162174
for _, p := range mimeMatch.apps {
163-
providers = append(providers, m.providers[p.Address])
175+
providers = append(providers, m.providers[p.provider.Address])
164176
}
165177
return providers, nil
166178
}
167179

168-
func providerIsDefaultForMimeType(p *registrypb.ProviderInfo, mime *mimeTypeConfig) bool {
169-
return p.Address == mime.DefaultApp || p.Name == mime.DefaultApp
170-
}
171-
172180
func (m *manager) AddProvider(ctx context.Context, p *registrypb.ProviderInfo) error {
173181
m.Lock()
174182
defer m.Unlock()
@@ -232,7 +240,7 @@ func (m *manager) ListSupportedMimeTypes(ctx context.Context) ([]*registrypb.Mim
232240
Name: mime.Name,
233241
Description: mime.Description,
234242
Icon: mime.Icon,
235-
AppProviders: mime.apps,
243+
AppProviders: mime.apps.getOrderedProviderByPriority(),
236244
AllowCreation: mime.AllowCreation,
237245
DefaultApplication: mime.DefaultApp,
238246
})
@@ -242,17 +250,17 @@ func (m *manager) ListSupportedMimeTypes(ctx context.Context) ([]*registrypb.Mim
242250
return res, nil
243251
}
244252

245-
// prepend an AppProvider obj to the list
246-
func prependProvider(n *registrypb.ProviderInfo, lst []*registrypb.ProviderInfo) []*registrypb.ProviderInfo {
247-
lst = append(lst, &registrypb.ProviderInfo{})
248-
copy(lst[1:], lst)
249-
lst[0] = n
250-
return lst
253+
func (h providerHeap) getOrderedProviderByPriority() []*registrypb.ProviderInfo {
254+
providers := make([]*registrypb.ProviderInfo, 0, h.Len())
255+
for _, pp := range h {
256+
providers = append(providers, pp.provider)
257+
}
258+
return providers
251259
}
252260

253-
func getIndex(lst []*registrypb.ProviderInfo, s *registrypb.ProviderInfo) (int, bool) {
254-
for i, e := range lst {
255-
if equalsProviderInfo(e, s) {
261+
func getIndex(h providerHeap, s *registrypb.ProviderInfo) (int, bool) {
262+
for i, e := range h {
263+
if equalsProviderInfo(e.provider, s) {
256264
return i, true
257265
}
258266
}
@@ -268,15 +276,7 @@ func (m *manager) SetDefaultProviderForMimeType(ctx context.Context, mimeType st
268276
mime := mimeInterface.(*mimeTypeConfig)
269277
mime.DefaultApp = p.Address
270278

271-
if index, in := getIndex(mime.apps, p); in {
272-
// the element is in the list, we will remove it
273-
// TODO (gdelmont): not the best way to remove an element from a slice
274-
// but maybe we want to keep the order?
275-
mime.apps = append(mime.apps[:index], mime.apps[index+1:]...)
276-
}
277-
// prepend it to the front of the list
278-
mime.apps = prependProvider(p, mime.apps)
279-
279+
registerProvider(p, mime)
280280
} else {
281281
// the mime type should be already registered as config in the AppRegistry
282282
// we will create a new entry fot the mimetype, but leaving a warning for
@@ -288,9 +288,17 @@ func (m *manager) SetDefaultProviderForMimeType(ctx context.Context, mimeType st
288288
}
289289

290290
func dummyMimeType(m string, apps []*registrypb.ProviderInfo) *mimeTypeConfig {
291+
appsHeap := providerHeap{}
292+
for _, p := range apps {
293+
heap.Push(&appsHeap, providerWithPriority{
294+
provider: p,
295+
priority: getPriority(p),
296+
})
297+
}
298+
291299
return &mimeTypeConfig{
292300
MimeType: m,
293-
apps: apps,
301+
apps: appsHeap,
294302
//Extension: "", // there is no meaningful general extension, so omit it
295303
//Name: "", // there is no meaningful general name, so omit it
296304
//Description: "", // there is no meaningful general description, so omit it
@@ -337,3 +345,33 @@ func providersEquals(l1, l2 []*registrypb.ProviderInfo) bool {
337345
}
338346
return true
339347
}
348+
349+
type providerWithPriority struct {
350+
provider *registrypb.ProviderInfo
351+
priority uint64
352+
}
353+
354+
type providerHeap []providerWithPriority
355+
356+
func (h providerHeap) Len() int {
357+
return len(h)
358+
}
359+
360+
func (h providerHeap) Less(i, j int) bool {
361+
return h[i].priority > h[j].priority
362+
}
363+
364+
func (h providerHeap) Swap(i, j int) {
365+
h[i], h[j] = h[j], h[i]
366+
}
367+
368+
func (h *providerHeap) Push(x interface{}) {
369+
*h = append(*h, x.(providerWithPriority))
370+
}
371+
372+
func (h *providerHeap) Pop() interface{} {
373+
last := len(*h) - 1
374+
x := (*h)[last]
375+
*h = (*h)[:last]
376+
return x
377+
}

0 commit comments

Comments
 (0)