Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
engine
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
AURA
engine
Commits
3e7594e5
Commit
3e7594e5
authored
3 years ago
by
David Trattnig
Browse files
Options
Downloads
Patches
Plain Diff
Fix for preloading.
#78
parent
a9d38e79
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/control.py
+40
-39
40 additions, 39 deletions
src/control.py
src/scheduling/scheduler.py
+28
-22
28 additions, 22 deletions
src/scheduling/scheduler.py
with
68 additions
and
61 deletions
src/control.py
+
40
−
39
View file @
3e7594e5
...
...
@@ -184,21 +184,23 @@ class EngineExecutor(Timer):
Primarily used for automations performed by the scheduler.
"""
_lock
=
None
timer_store
:
dict
=
{}
logger
=
logging
.
getLogger
(
"
AuraEngine
"
)
initialized
=
None
timer_store
=
{}
parent_timer
=
None
child_timer
=
None
direct_exec
=
None
timer_id
=
None
timer_type
=
None
EVENT_ON_READY
=
"
on_ready
"
_lock
=
None
direct_exec
:
bool
=
None
parent_timer
:
Timer
=
None
child_timer
:
Timer
=
None
timer_id
:
str
=
None
timer_type
:
str
=
None
func
=
None
param
=
None
diff
=
None
dt
=
None
def
__init__
(
self
,
timer_type
=
"
BASE
"
,
parent_timer
=
None
,
due_time
=
None
,
func
=
None
,
param
=
None
):
def
__init__
(
self
,
timer_type
:
str
=
"
BASE
"
,
parent_timer
:
Timer
=
None
,
due_time
=
None
,
func
=
None
,
param
=
None
):
"""
Constructor
...
...
@@ -209,7 +211,6 @@ class EngineExecutor(Timer):
func (function): The function to be called
param (object): Parameter passt to the function
"""
self
.
initialized
=
False
self
.
_lock
=
Lock
()
from
src.engine
import
Engine
now_unix
=
Engine
.
engine_time
()
...
...
@@ -224,9 +225,8 @@ class EngineExecutor(Timer):
self
.
timer_type
=
timer_type
self
.
timer_id
=
f
"
{
timer_type
}
:
{
func
.
__name__
}
:
{
due_time
}
"
if
not
due_time
:
diff
=
0
else
:
diff
=
0
if
due_time
:
diff
=
due_time
-
now_unix
self
.
diff
=
diff
...
...
@@ -240,32 +240,22 @@ class EngineExecutor(Timer):
else
:
if
diff
<
0
:
msg
=
f
"
Timer
'
{
self
.
timer_id
}
'
is due in the past. Executing immediately ...
"
self
.
logger
.
error
(
SU
.
red
(
msg
))
self
.
logger
.
warn
(
SU
.
yellow
(
msg
))
self
.
exec_now
()
elif
diff
==
0
:
self
.
logger
.
info
(
f
"
Timer
'
{
self
.
timer_id
}
'
to be executed immediately
"
)
self
.
logger
.
debug
(
f
"
Timer
'
{
self
.
timer_id
}
'
to be executed immediately
"
)
self
.
exec_now
()
else
:
self
.
logger
.
debug
(
f
"
Timer
'
{
self
.
timer_id
}
'
to be executed in default manner
"
)
self
.
exec_timed
()
self
.
start
()
def
on_ready
(
self
,
func
):
"""
Calls the passed function `func` when the timer is ready.
"""
while
self
.
initialized
==
False
:
timer
.
sleep
(
0.001
)
self
.
logger
.
info
(
SU
.
orange
(
"
Waiting until the EngineExecutor is done with initialization...
"
))
if
not
self
.
direct_exec
:
#TODO Evaluate if we should join for direct exec too
self
.
join
()
func
()
def
wait_for_parent
(
self
):
"""
Child timers are dependend on their parents. So let
'
s wait until parents are done with their stuff.
@private
Child timers are dependend on their parents. So let
'
s wait until parents are done with their stuff => finished execution.
Checks the parent state to be finished every 0.2 seconds.
"""
if
self
.
parent_timer
:
while
self
.
parent_timer
.
is_alive
():
...
...
@@ -275,22 +265,27 @@ class EngineExecutor(Timer):
def
exec_now
(
self
):
"""
@private
Immediate execution within a thread. It
'
s not stored in the timer store.
A
ssigns the `timer_id` as the thread name.
It also a
ssigns the `timer_id` as the thread name.
"""
self
.
direct_exec
=
True
self
.
wait_for_parent
()
thread
=
Thread
(
name
=
self
.
timer_id
,
target
=
self
.
func
,
args
=
(
self
.
param
,))
time
.
sleep
(
0.2
)
thread
.
start
()
self
.
initialized
=
True
def
exec_timed
(
self
):
"""
Timed execution in a thread.
@private
Assigns the `timer_id` as the thread name.
Timed execution in a thread. This method instroduces a slight delay to ensure
the thread is properly initialized before starting it.
It also assigns the `timer_id` as the thread name.
"""
def
wrapper_func
(
param
=
None
):
self
.
wait_for_parent
()
...
...
@@ -298,18 +293,22 @@ class EngineExecutor(Timer):
else
:
self
.
func
()
super
().
__init__
(
self
.
diff
,
wrapper_func
,
(
self
.
param
,))
self
.
_name
=
self
.
timer_id
self
.
initialized
=
True
time
.
sleep
(
0.2
)
self
.
start
()
def
update_store
(
self
):
"""
@private
Adds the instance to the store and cancels any previously existing commands.
If a timer with the given ID is already existing but also already executed,
then it is not added to the store. In such case the method returns `False`.
Returns:
(Boolean): True if the timer has been added to the store
(Boolean): True if the timer has been added to the store. False if the
timer is already existing but dead.
"""
with
self
.
_lock
:
existing_command
=
None
...
...
@@ -337,6 +336,8 @@ class EngineExecutor(Timer):
def
is_alive
(
self
):
"""
@private
Returns true if the command is still due to be executed.
"""
if
self
.
direct_exec
==
True
:
...
...
@@ -346,7 +347,7 @@ class EngineExecutor(Timer):
def
__str__
(
self
):
"""
String represenation of the timer.
String represen
t
ation of the timer.
"""
return
f
"
[
{
self
.
timer_id
}
] exec at
{
str
(
self
.
dt
)
}
(alive:
{
self
.
is_alive
()
}
)
"
...
...
@@ -372,7 +373,7 @@ class EngineExecutor(Timer):
@staticmethod
def
log_commands
():
"""
Prints a list of recent active and inactive timers.
Prints a list of recent active and inactive timers
to the logger
.
"""
msg
=
SU
.
blue
(
"
\n
[ ENGINE COMMAND QUEUE ]
\n
"
)
EngineExecutor
.
remove_stale_timers
()
...
...
@@ -383,7 +384,7 @@ class EngineExecutor(Timer):
else
:
for
timer
in
timers
:
if
not
timer
.
parent_timer
:
line
=
f
"
=>
{
str
(
timer
)
}
\n
"
#
line
=
f
"
=>
{
str
(
timer
)
}
\n
"
if
timer
.
is_alive
():
line
=
SU
.
green
(
line
)
msg
+=
line
...
...
This diff is collapsed.
Click to expand it.
src/scheduling/scheduler.py
+
28
−
22
View file @
3e7594e5
...
...
@@ -45,17 +45,16 @@ class AuraScheduler(threading.Thread):
- Executes engine actions in an automated fashion
"""
config
=
None
config
:
AuraConfig
=
None
logger
=
None
engine
=
None
exit_event
=
None
timeslot_renderer
=
None
programme
=
None
engine
:
Engine
=
None
exit_event
:
threading
.
Event
=
None
timeslot_renderer
:
TimeslotRenderer
=
None
programme
:
ProgrammeService
=
None
message_timer
=
[]
fallback
=
None
is_initialized
=
None
is_initialized
=
None
is_initialized
:
bool
=
None
is_engine_ready
:
bool
=
None
def
__init__
(
self
,
engine
,
fallback_manager
):
...
...
@@ -407,10 +406,11 @@ class TimeslotCommand(EngineExecutor):
"""
Command for triggering start and end of timeslot events.
"""
engine
=
None
config
=
None
engine
:
Engine
=
None
config
:
AuraConfig
=
None
def
__init__
(
self
,
engine
,
timeslot
):
def
__init__
(
self
,
engine
:
Engine
,
timeslot
):
"""
Constructor
...
...
@@ -421,12 +421,15 @@ class TimeslotCommand(EngineExecutor):
self
.
config
=
AuraConfig
()
self
.
engine
=
engine
now_unix
=
SU
.
timestamp
()
fade_out_time
=
float
(
self
.
config
.
get
(
"
fade_out_time
"
))
start_fade_out
=
timeslot
.
end_unix
-
fade_out_time
self
.
logger
.
info
(
f
"
Fading out timeslot in
{
start_fade_out
}
seconds at
{
timeslot
.
timeslot_end
}
| Timeslot:
{
timeslot
}
"
)
# Initialize the "fade in" EngineExecuter and instatiate a connected child EngineExecuter for "fade out" when the parent is ready
start_fade_in
=
timeslot
.
start_unix
-
now_unix
start_fade_out
=
timeslot
.
end_unix
-
now_unix
-
fade_out_time
self
.
logger
.
debug
(
f
"
Fading in timeslot in
{
start_fade_in
}
seconds at
{
SU
.
fmt_time
(
timeslot
.
start_unix
)
}
| Timeslot:
{
timeslot
}
"
)
self
.
logger
.
debug
(
f
"
Fading out timeslot in
{
start_fade_out
}
seconds at
{
SU
.
fmt_time
(
timeslot
.
end_unix
-
fade_out_time
)
}
| Timeslot:
{
timeslot
}
"
)
# Initialize the "fade in" EngineExecuter and instantiate a connected child EngineExecuter for "fade out" when the parent is ready
super
().
__init__
(
"
TIMESLOT
"
,
None
,
timeslot
.
start_unix
,
self
.
do_start_timeslot
,
timeslot
)
self
.
on_ready
(
lambda
:
EngineExecutor
(
"
TIMESLOT
"
,
self
,
start_
fade_out
,
self
.
do_end_timeslot
,
timeslot
)
)
EngineExecutor
(
"
TIMESLOT
"
,
self
,
timeslot
.
end_unix
-
fade_out
_time
,
self
.
do_end_timeslot
,
timeslot
)
def
do_start_timeslot
(
self
,
timeslot
):
...
...
@@ -456,10 +459,11 @@ class PlayCommand(EngineExecutor):
"""
Command for triggering timed preloading and playing as a child command.
"""
engine
=
None
config
=
None
engine
:
Engine
=
None
config
:
AuraConfig
=
None
def
__init__
(
self
,
engine
,
entries
):
def
__init__
(
self
,
engine
:
Engine
,
entries
):
"""
Constructor
...
...
@@ -470,11 +474,13 @@ class PlayCommand(EngineExecutor):
self
.
config
=
AuraConfig
()
self
.
engine
=
engine
start_preload
=
entries
[
0
].
start_unix
-
self
.
config
.
get
(
"
preload_offset
"
)
preload_offset
=
self
.
config
.
get
(
"
preload_offset
"
)
start_preload
=
entries
[
0
].
start_unix
-
preload_offset
start_play
=
entries
[
0
].
start_unix
self
.
logger
.
debug
(
f
"
Preloading entries at
{
SU
.
fmt_time
(
start_preload
)
}
,
{
preload_offset
}
seconds before playing it at
{
SU
.
fmt_time
(
start_play
)
}
"
)
# Initialize the "preload" EngineExecuter and attach a child `PlayCommand` to the "on_ready" event handler
preload_timer
=
super
().
__init__
(
"
PRELOAD
"
,
None
,
start_preload
,
self
.
do_preload
,
entries
)
self
.
on_ready
(
lambda
:
EngineExecutor
(
"
PLAY
"
,
self
,
start_play
,
self
.
do_play
,
entries
)
)
super
().
__init__
(
"
PRELOAD
"
,
None
,
start_preload
,
self
.
do_preload
,
entries
)
EngineExecutor
(
"
PLAY
"
,
self
,
start_play
,
self
.
do_play
,
entries
)
def
do_preload
(
self
,
entries
):
...
...
@@ -504,7 +510,7 @@ class PlayCommand(EngineExecutor):
# Let 'em play anyway ...
self
.
logger
.
critical
(
SU
.
red
(
"
PLAY: The entry/entries are not yet ready to be played (Entries: %s)
"
%
ResourceUtil
.
get_entries_string
(
entries
)))
while
(
entries
[
-
1
].
status
!=
EntryPlayState
.
READY
):
self
.
logger
.
info
(
"
PLAY: Wait a little until preloading is done ...
"
)
self
.
logger
.
info
(
"
PLAY: Wait a little
bit
until preloading is done ...
"
)
time
.
sleep
(
2
)
self
.
engine
.
player
.
play
(
entries
[
0
],
TransitionType
.
FADE
)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment