mirror of https://github.com/grafana/grafana
Rendering service - add optional RenderingSession (#44098)
* rendering service changes: - make node-renderer request timeout configurable - introduce optional RenderingSession providing a long-lived session key * remove console logs * added comment explaining empty "afterRequest" method * fix compilation error * update imports formatting * Update pkg/services/rendering/interface.go Co-authored-by: Agnès Toulet <35176601+AgnesToulet@users.noreply.github.com> * Update pkg/services/rendering/rendering.go Co-authored-by: Agnès Toulet <35176601+AgnesToulet@users.noreply.github.com> * review fix: extract renderKey related functions/structs to auth.go * #44449: private'd `rendering.getRequestTimeout` Co-authored-by: Agnès Toulet <35176601+AgnesToulet@users.noreply.github.com>pull/45191/head
parent
3c334cd8ba
commit
5148250366
@ -0,0 +1,120 @@ |
||||
package rendering |
||||
|
||||
import ( |
||||
"context" |
||||
"fmt" |
||||
"time" |
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log" |
||||
"github.com/grafana/grafana/pkg/infra/remotecache" |
||||
"github.com/grafana/grafana/pkg/util" |
||||
) |
||||
|
||||
const renderKeyPrefix = "render-%s" |
||||
|
||||
type RenderUser struct { |
||||
OrgID int64 |
||||
UserID int64 |
||||
OrgRole string |
||||
} |
||||
|
||||
func (rs *RenderingService) GetRenderUser(ctx context.Context, key string) (*RenderUser, bool) { |
||||
val, err := rs.RemoteCacheService.Get(ctx, fmt.Sprintf(renderKeyPrefix, key)) |
||||
if err != nil { |
||||
rs.log.Error("Failed to get render key from cache", "error", err) |
||||
} |
||||
|
||||
if val != nil { |
||||
if user, ok := val.(*RenderUser); ok { |
||||
return user, true |
||||
} |
||||
} |
||||
|
||||
return nil, false |
||||
} |
||||
|
||||
func setRenderKey(cache *remotecache.RemoteCache, ctx context.Context, opts AuthOpts, renderKey string, expiry time.Duration) error { |
||||
err := cache.Set(ctx, fmt.Sprintf(renderKeyPrefix, renderKey), &RenderUser{ |
||||
OrgID: opts.OrgID, |
||||
UserID: opts.UserID, |
||||
OrgRole: string(opts.OrgRole), |
||||
}, expiry) |
||||
return err |
||||
} |
||||
|
||||
func generateAndSetRenderKey(cache *remotecache.RemoteCache, ctx context.Context, opts AuthOpts, expiry time.Duration) (string, error) { |
||||
key, err := util.GetRandomString(32) |
||||
if err != nil { |
||||
return "", err |
||||
} |
||||
|
||||
err = setRenderKey(cache, ctx, opts, key, expiry) |
||||
if err != nil { |
||||
return "", err |
||||
} |
||||
|
||||
return key, nil |
||||
} |
||||
|
||||
type longLivedRenderKeyProvider struct { |
||||
cache *remotecache.RemoteCache |
||||
log log.Logger |
||||
renderKey string |
||||
authOpts AuthOpts |
||||
sessionOpts SessionOpts |
||||
} |
||||
|
||||
func (rs *RenderingService) CreateRenderingSession(ctx context.Context, opts AuthOpts, sessionOpts SessionOpts) (Session, error) { |
||||
renderKey, err := generateAndSetRenderKey(rs.RemoteCacheService, ctx, opts, sessionOpts.Expiry) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
return &longLivedRenderKeyProvider{ |
||||
log: rs.log, |
||||
renderKey: renderKey, |
||||
cache: rs.RemoteCacheService, |
||||
authOpts: opts, |
||||
sessionOpts: sessionOpts, |
||||
}, nil |
||||
} |
||||
|
||||
func deleteRenderKey(cache *remotecache.RemoteCache, log log.Logger, ctx context.Context, renderKey string) { |
||||
err := cache.Delete(ctx, fmt.Sprintf(renderKeyPrefix, renderKey)) |
||||
if err != nil { |
||||
log.Error("Failed to delete render key", "error", err) |
||||
} |
||||
} |
||||
|
||||
type perRequestRenderKeyProvider struct { |
||||
cache *remotecache.RemoteCache |
||||
log log.Logger |
||||
keyExpiry time.Duration |
||||
} |
||||
|
||||
func (r *perRequestRenderKeyProvider) get(ctx context.Context, opts AuthOpts) (string, error) { |
||||
return generateAndSetRenderKey(r.cache, ctx, opts, r.keyExpiry) |
||||
} |
||||
|
||||
func (r *perRequestRenderKeyProvider) afterRequest(ctx context.Context, opts AuthOpts, renderKey string) { |
||||
deleteRenderKey(r.cache, r.log, ctx, renderKey) |
||||
} |
||||
|
||||
func (r *longLivedRenderKeyProvider) get(ctx context.Context, opts AuthOpts) (string, error) { |
||||
if r.sessionOpts.RefreshExpiryOnEachRequest { |
||||
err := setRenderKey(r.cache, ctx, opts, r.renderKey, r.sessionOpts.Expiry) |
||||
if err != nil { |
||||
r.log.Error("Failed to refresh render key", "error", err, "renderKey", r.renderKey) |
||||
} |
||||
} |
||||
return r.renderKey, nil |
||||
} |
||||
|
||||
func (r *longLivedRenderKeyProvider) afterRequest(ctx context.Context, opts AuthOpts, renderKey string) { |
||||
// do nothing - renderKey from longLivedRenderKeyProvider is deleted only after session expires
|
||||
// or someone calls session.Dispose()
|
||||
} |
||||
|
||||
func (r *longLivedRenderKeyProvider) Dispose(ctx context.Context) { |
||||
deleteRenderKey(r.cache, r.log, ctx, r.renderKey) |
||||
} |
Loading…
Reference in new issue