-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
health: Implement multistream status integrated with stream status (#7)
* pkg/data: Store events time as millis, not nano int64 is not JSON serializable, so we better avoid it * Create new WebhookEvent type * pkg/data: Create MultistreamWebhookPayload type * pkd/data: Make webhook event payload optional * health: Crete new multistream reducer for ms status * health: Add multistream reducer to pipeline&health * health: Use pointers of status to avoid racy copies @darkdarkdragon pointed out on #6 that a copy is not atomic so could have issues when copying a value without holding a lock. I don't want to increaase the usage of the lock either, so decided to change the status to a pointer instead so we will have a consistent view of the status, not one in between a copy. Also, this is probably better for perf anyway since we were copying that big object multiple times on every event processing. Better like this I guess. * health: Create root MultistreamHealthy condition * WIP: Add TODO to fix Status recreation issue * api: Accept timestamps only in unix milliseconds (or RFC3339) * health: Fix all comments from self-review * pkg/event: Update bindings one existing streams Now we'll make our first deploy already with a change to the queue bindings. It already feels overkill to have to change the stream name to do that, so I'm changing the logic on stream_consumer to always set the bindings on the existing stream, even if it already existed before. This works more similarly to how other AMQP clients generally do this. * health: Add some helpers for Status immutability Will reduce the boilerplate a bit. We should keep iterating on this on the following code changes, but I believe this is enough for this change. * reducers: Namespace RealTime and NoErrors conditions We might want to have other "no errors" and "real time" flags in the future, so we better not start with too generic names here. * docker-compose: Create webhooks exchange as well * health: Rename MultistreamHealthy to Multistreaming Consistency with Transcoding condition. * health: Fix webhook exchange name * pkg/data: Change ManifestID field to StreamID * api: Fix health status JSON response
- Loading branch information
Showing
17 changed files
with
321 additions
and
111 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package reducers | ||
|
||
import ( | ||
"encoding/json" | ||
"strings" | ||
"time" | ||
|
||
"github.com/golang/glog" | ||
"github.com/livepeer/livepeer-data/health" | ||
"github.com/livepeer/livepeer-data/pkg/data" | ||
"github.com/livepeer/livepeer-data/pkg/event" | ||
) | ||
|
||
const ( | ||
ConditionMultistreaming health.ConditionType = "Multistreaming" | ||
|
||
webhooksExchange = "webhook_default_exchange" | ||
multistreamBindingKey = "events.multistream.#" | ||
) | ||
|
||
type MultistreamReducer struct{} | ||
|
||
func (t MultistreamReducer) Bindings() []event.BindingArgs { | ||
return []event.BindingArgs{{Exchange: webhooksExchange, Key: multistreamBindingKey}} | ||
} | ||
|
||
func (t MultistreamReducer) Conditions() []health.ConditionType { | ||
return []health.ConditionType{ConditionMultistreaming} | ||
} | ||
|
||
func (t MultistreamReducer) Reduce(current *health.Status, _ interface{}, evtIface data.Event) (*health.Status, interface{}) { | ||
evt, ok := evtIface.(*data.WebhookEvent) | ||
if !ok { | ||
return current, nil | ||
} | ||
if !strings.HasPrefix(evt.Event, "multistream.") { | ||
return current, nil | ||
} | ||
|
||
ts := evt.Timestamp() | ||
var payload data.MultistreamWebhookPayload | ||
if err := json.Unmarshal(evt.Payload, &payload); err != nil { | ||
glog.Errorf("Error parsing multistream webhook payload. err=%q", err) | ||
return current, nil | ||
} | ||
target := payload.Target | ||
|
||
multistream := current.MultistreamCopy() | ||
multistream, idx := findOrCreateMultistreamStatus(multistream, target) | ||
if status := connectedStatusFromEvent(evt); status != nil { | ||
currConnected := multistream[idx].Connected | ||
multistream[idx] = &health.MultistreamStatus{ | ||
Target: target, | ||
Connected: health.NewCondition("", ts, status, nil, currConnected), | ||
} | ||
} | ||
|
||
conditions := current.ConditionsCopy() | ||
for i, cond := range conditions { | ||
if cond.Type == ConditionMultistreaming { | ||
status := allTargetsConnected(multistream) | ||
conditions[i] = health.NewCondition(cond.Type, ts, &status, nil, cond) | ||
} | ||
} | ||
|
||
return health.NewMergedStatus(current, health.Status{ | ||
Conditions: conditions, | ||
Multistream: multistream, | ||
}), nil | ||
} | ||
|
||
func allTargetsConnected(multistream []*health.MultistreamStatus) bool { | ||
for _, ms := range multistream { | ||
if ms.Connected.Status == nil || !*ms.Connected.Status { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
|
||
func connectedStatusFromEvent(evt *data.WebhookEvent) *bool { | ||
var connected bool | ||
switch evt.Event { | ||
case "multistream.connected": | ||
connected = true | ||
case "multistream.disconnected", "multistream.error": | ||
connected = false | ||
default: | ||
glog.Errorf("Unknown multistream webhook event. event=%q", evt.Event) | ||
return nil | ||
} | ||
return &connected | ||
} | ||
|
||
func findOrCreateMultistreamStatus(multistream []*health.MultistreamStatus, target data.MultistreamTargetInfo) ([]*health.MultistreamStatus, int) { | ||
for idx, ms := range multistream { | ||
if targetsEq(ms.Target, target) { | ||
return multistream, idx | ||
} | ||
} | ||
|
||
multistream = append(multistream, &health.MultistreamStatus{ | ||
Target: target, | ||
Connected: health.NewCondition("", time.Time{}, nil, nil, nil), | ||
}) | ||
return multistream, len(multistream) - 1 | ||
} | ||
|
||
func targetsEq(t1, t2 data.MultistreamTargetInfo) bool { | ||
return t1.Profile == t2.Profile && t1.ID == t2.ID | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.