Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
小 白蛋
Nomad
Commits
45c87280
Unverified
Commit
45c87280
authored
6 years ago
by
Nick Ethier
Browse files
Options
Download
Email Patches
Plain Diff
plugin/drivers: rework eventer and change naming stream -> consumer
parent
e4f80872
Branches unavailable
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
plugins/drivers/utils/eventer.go
+67
-32
plugins/drivers/utils/eventer.go
plugins/drivers/utils/eventer_test.go
+36
-16
plugins/drivers/utils/eventer_test.go
with
103 additions
and
48 deletions
+103
-48
plugins/drivers/utils/eventer.go
+
67
-
32
View file @
45c87280
package
utils
import
(
"fmt"
"sync"
"time"
hclog
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/nomad/plugins/drivers"
"golang.org/x/net/context"
)
var
(
//DefaultSendEventTimeout is the timeout used when publishing events to consumers
//
DefaultSendEventTimeout is the timeout used when publishing events to consumers
DefaultSendEventTimeout
=
2
*
time
.
Second
)
// Eventer is a utility to control broadcast of TaskEvents to multiple consumers.
// It also implements the Task
Sta
ts func in the DriverPlugin interface so that
// It also implements the Task
Even
ts func in the DriverPlugin interface so that
// it can be embedded in a implementing driver struct.
type
Eventer
struct
{
sync
.
RWMutex
consumersLock
sync
.
RWMutex
// events is a channel were events to be broadcasted are sent
events
chan
*
drivers
.
TaskEvent
//
strea
mers is a slice of
c
onsumers to broadcast events to
// access is gaurded by RWMutex
strea
mers
[]
*
event
Strea
mer
//
consu
mers is a slice of
eventC
onsumers to broadcast events to
.
// access is gaurded by
consumersLock
RWMutex
consu
mers
[]
*
event
Consu
mer
// stop chan to allow control of event loop shutdown
stop
chan
struct
{}
// ctx to allow control of event loop shutdown
ctx
context
.
Context
// done tracks if the event loop has stopped due to the ctx being done
done
bool
logger
hclog
.
Logger
}
// NewEventer returns an Eventer with a running event loop that can be stopped
// by closing the given stop channel
func
NewEventer
(
stop
chan
struct
{}
)
*
Eventer
{
func
NewEventer
(
ctx
context
.
Context
,
logger
hclog
.
Logger
)
*
Eventer
{
e
:=
&
Eventer
{
events
:
make
(
chan
*
drivers
.
TaskEvent
),
stop
:
stop
,
ctx
:
ctx
,
logger
:
logger
,
}
go
e
.
eventLoop
()
return
e
...
...
@@ -46,56 +54,83 @@ func NewEventer(stop chan struct{}) *Eventer {
func
(
e
*
Eventer
)
eventLoop
()
{
for
{
select
{
case
<-
e
.
stop
:
for
_
,
stream
:=
range
e
.
streamers
{
close
(
stream
.
ch
)
}
case
<-
e
.
ctx
.
Done
()
:
e
.
done
=
true
close
(
e
.
events
)
return
case
event
:=
<-
e
.
events
:
e
.
RLock
()
for
_
,
stream
:=
range
e
.
strea
mers
{
stream
.
send
(
event
)
e
.
consumersLock
.
RLock
()
for
_
,
consumer
:=
range
e
.
consu
mers
{
consumer
.
send
(
event
)
}
e
.
RUnlock
()
e
.
consumersLock
.
RUnlock
()
}
}
}
type
event
Strea
mer
struct
{
type
event
Consu
mer
struct
{
timeout
time
.
Duration
ctx
context
.
Context
ch
chan
*
drivers
.
TaskEvent
logger
hclog
.
Logger
}
func
(
s
*
event
Strea
mer
)
send
(
event
*
drivers
.
TaskEvent
)
{
func
(
c
*
event
Consu
mer
)
send
(
event
*
drivers
.
TaskEvent
)
{
select
{
case
<-
time
.
After
(
s
.
timeout
)
:
case
<-
s
.
ctx
.
Done
()
:
case
s
.
ch
<-
event
:
case
<-
time
.
After
(
c
.
timeout
)
:
c
.
logger
.
Warn
(
"timeout sending event"
,
"task_id"
,
event
.
TaskID
,
"message"
,
event
.
Message
)
case
<-
c
.
ctx
.
Done
()
:
case
c
.
ch
<-
event
:
}
}
func
(
e
*
Eventer
)
new
Stream
(
ctx
context
.
Context
)
<-
chan
*
drivers
.
TaskEvent
{
e
.
Lock
()
defer
e
.
Unlock
()
func
(
e
*
Eventer
)
new
Consumer
(
ctx
context
.
Context
)
*
eventConsumer
{
e
.
consumersLock
.
Lock
()
defer
e
.
consumersLock
.
Unlock
()
stream
:=
&
event
Strea
mer
{
consumer
:=
&
event
Consu
mer
{
ch
:
make
(
chan
*
drivers
.
TaskEvent
),
ctx
:
ctx
,
timeout
:
DefaultSendEventTimeout
,
logger
:
e
.
logger
,
}
e
.
strea
mers
=
append
(
e
.
strea
mers
,
stream
)
e
.
consu
mers
=
append
(
e
.
consu
mers
,
consumer
)
return
stream
.
ch
return
consumer
}
// TaskEvents is an implementation of the DriverPlugin.TaskEvents function
func
(
e
*
Eventer
)
TaskEvents
(
ctx
context
.
Context
)
(
<-
chan
*
drivers
.
TaskEvent
,
error
)
{
stream
:=
e
.
newStream
(
ctx
)
return
stream
,
nil
consumer
:=
e
.
newConsumer
(
ctx
)
go
e
.
handleConsumer
(
consumer
)
return
consumer
.
ch
,
nil
}
func
(
e
*
Eventer
)
handleConsumer
(
consumer
*
eventConsumer
)
{
// wait for consumer or eventer ctx to finish
select
{
case
<-
consumer
.
ctx
.
Done
()
:
case
<-
e
.
ctx
.
Done
()
:
}
e
.
consumersLock
.
Lock
()
defer
e
.
consumersLock
.
Unlock
()
defer
close
(
consumer
.
ch
)
filtered
:=
e
.
consumers
[
:
0
]
for
_
,
c
:=
range
e
.
consumers
{
if
c
!=
consumer
{
filtered
=
append
(
filtered
,
c
)
}
}
e
.
consumers
=
filtered
}
// EmitEvent can be used to broadcast a new event
func
(
e
*
Eventer
)
EmitEvent
(
event
*
drivers
.
TaskEvent
)
{
func
(
e
*
Eventer
)
EmitEvent
(
event
*
drivers
.
TaskEvent
)
error
{
if
e
.
done
{
return
fmt
.
Errorf
(
"error sending event, context canceled"
)
}
e
.
events
<-
event
return
nil
}
This diff is collapsed.
Click to expand it.
plugins/drivers/utils/eventer_test.go
+
36
-
16
View file @
45c87280
...
...
@@ -6,6 +6,7 @@ import (
"testing"
"time"
"github.com/hashicorp/nomad/helper/testlog"
"github.com/hashicorp/nomad/plugins/drivers"
"github.com/stretchr/testify/require"
)
...
...
@@ -14,8 +15,8 @@ func TestEventer(t *testing.T) {
t
.
Parallel
()
require
:=
require
.
New
(
t
)
stop
:=
make
(
chan
struct
{}
)
e
:=
NewEventer
(
stop
)
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
()
)
e
:=
NewEventer
(
ctx
,
testlog
.
HCLogger
(
t
)
)
events
:=
[]
*
drivers
.
TaskEvent
{
{
...
...
@@ -32,9 +33,11 @@ func TestEventer(t *testing.T) {
},
}
consumer1
,
err
:=
e
.
TaskEvents
(
context
.
Background
())
ctx1
,
cancel1
:=
context
.
WithCancel
(
context
.
Background
())
consumer1
,
err
:=
e
.
TaskEvents
(
ctx1
)
require
.
NoError
(
err
)
consumer2
,
err
:=
e
.
TaskEvents
(
context
.
Background
())
ctx2
:=
(
context
.
Background
())
consumer2
,
err
:=
e
.
TaskEvents
(
ctx2
)
require
.
NoError
(
err
)
var
buffer1
,
buffer2
[]
*
drivers
.
TaskEvent
...
...
@@ -42,31 +45,48 @@ func TestEventer(t *testing.T) {
wg
.
Add
(
2
)
go
func
()
{
defer
wg
.
Done
()
for
{
event
,
ok
:=
<-
consumer1
if
!
ok
{
return
}
var
i
int
for
event
:=
range
consumer1
{
i
++
buffer1
=
append
(
buffer1
,
event
)
if
i
==
3
{
break
}
}
}()
go
func
()
{
defer
wg
.
Done
()
for
{
event
,
ok
:=
<-
consumer2
if
!
ok
{
return
}
var
i
int
for
event
:=
range
consumer2
{
i
++
buffer2
=
append
(
buffer2
,
event
)
if
i
==
3
{
break
}
}
}()
for
_
,
event
:=
range
events
{
e
.
EmitEvent
(
event
)
require
.
NoError
(
e
.
EmitEvent
(
event
)
)
}
close
(
stop
)
wg
.
Wait
()
require
.
Exactly
(
events
,
buffer1
)
require
.
Exactly
(
events
,
buffer2
)
cancel1
()
time
.
Sleep
(
100
*
time
.
Millisecond
)
require
.
Equal
(
1
,
len
(
e
.
consumers
))
require
.
NoError
(
e
.
EmitEvent
(
&
drivers
.
TaskEvent
{}))
ev
,
ok
:=
<-
consumer1
require
.
Nil
(
ev
)
require
.
False
(
ok
)
ev
,
ok
=
<-
consumer2
require
.
NotNil
(
ev
)
require
.
True
(
ok
)
cancel
()
time
.
Sleep
(
100
*
time
.
Millisecond
)
require
.
Zero
(
len
(
e
.
consumers
))
require
.
Error
(
e
.
EmitEvent
(
&
drivers
.
TaskEvent
{}))
}
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment
Menu
Projects
Groups
Snippets
Help