Skip to content

Commit 8e148b6

Browse files
committed
Time limit for resource_allocation_plot
1. Created time limit for resource_allocation_plot using signal library. 2. Don’t show failures in legend if no failures. 3. Added more robust print statements with timestamps. 4. Only populate commands to qiita_pet when plots were created.
1 parent 4032ed5 commit 8e148b6

File tree

2 files changed

+81
-32
lines changed

2 files changed

+81
-32
lines changed

qiita_db/meta_util.py

Lines changed: 68 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
from hashlib import md5
3737
from re import sub
3838
from json import loads, dump, dumps
39+
import signal
40+
import traceback
3941

4042
from qiita_db.util import create_nested_path, retrieve_resource_data
4143
from qiita_db.util import resource_allocation_plot
@@ -555,7 +557,8 @@ def generate_plugin_releases():
555557
f(redis_key, v)
556558

557559

558-
def update_resource_allocation_redis(active=True, verbose=False):
560+
def update_resource_allocation_redis(active=True, verbose=False,
561+
time_limit=300):
559562
"""Updates redis with plots and information about current software.
560563
561564
Parameters
@@ -564,7 +567,11 @@ def update_resource_allocation_redis(active=True, verbose=False):
564567
Defaults to True. Should only be False when testing.
565568
566569
verbose: boolean, optional
567-
Defaults to False. Prints status on what function
570+
Defaults to False. Prints status on what function is running.
571+
572+
time_limit: integer, optional
573+
Defaults to 300, representing 5 minutes. This is the limit for how long
574+
resource_allocation_plot function will run.
568575
569576
"""
570577
time = datetime.now().strftime('%m-%d-%y')
@@ -592,24 +599,24 @@ def update_resource_allocation_redis(active=True, verbose=False):
592599
cmd_name = command.name
593600
scommands[sname][sversion][cmd_name] = col_names
594601

595-
redis_key = 'resources:commands'
596-
r_client.set(redis_key, str(scommands))
597-
602+
# software commands for which resource allocations were sucessfully
603+
# calculated
604+
scommands_allocation = {}
598605
for sname, versions in scommands.items():
599606
for version, commands in versions.items():
600607
for cname, col_names in commands.items():
601608
df = retrieve_resource_data(cname, sname, version, COLUMNS)
602609
if verbose:
603-
print(("Retrieving allocation resources for " +
604-
f" software: {sname}" +
605-
f" version: {version}" +
606-
f" command: {cname}"))
610+
print(("\nRetrieving allocation resources for:\n" +
611+
f" software: {sname}\n" +
612+
f" version: {version}\n" +
613+
f" command: {cname}"))
607614
if len(df) == 0:
608615
if verbose:
609-
print(("No allocation resources available for" +
616+
print(("\nNo allocation resources available for" +
610617
f" software: {sname}" +
611618
f" version: {version}" +
612-
f" command: {cname}"))
619+
f" command: {cname}\n"))
613620
continue
614621
# column_name_str looks like col1*col2*col3, etc
615622
for col_name in col_names:
@@ -624,16 +631,38 @@ def update_resource_allocation_redis(active=True, verbose=False):
624631
else:
625632
new_column *= df_copy[curr_column]
626633
if verbose:
627-
print(("Building resource allocation plot for " +
628-
f" software: {sname}" +
629-
f" version: {version}" +
630-
f" command: {cname}" +
631-
f" column name: {col_name}"))
634+
print(
635+
("\nBuilding resource allocation plot for:\n" +
636+
f" software: {sname}\n" +
637+
f" version: {version}\n" +
638+
f" command: {cname}\n" +
639+
f" column name: {col_name}\n" +
640+
f" {datetime.now().strftime('%b %d %H:%M:%S')}"))
641+
642+
def timeout_handler(signum, frame):
643+
raise TimeoutError((
644+
"\nresource_allocation_plot " +
645+
"execution exceeded time limit." +
646+
"For:\n"
647+
f" software: {sname}\n" +
648+
f" version: {version}\n" +
649+
f" command: {cname}\n" +
650+
f" column name: {col_name}\n" +
651+
f" {datetime.now().strftime('%b %d %H:%M:%S')}"))
652+
653+
signal.signal(signal.SIGALRM, timeout_handler)
654+
signal.alarm(time_limit)
655+
try:
656+
fig, axs = resource_allocation_plot(df_copy,
657+
col_name,
658+
new_column,
659+
verbose=verbose)
660+
signal.alarm(0)
661+
except TimeoutError:
662+
print("Timeout reached!")
663+
traceback.print_exc()
664+
continue
632665

633-
fig, axs = resource_allocation_plot(df_copy,
634-
col_name,
635-
new_column,
636-
verbose=verbose)
637666
titles = [0, 0]
638667
images = [0, 0]
639668

@@ -685,14 +714,28 @@ def update_resource_allocation_redis(active=True, verbose=False):
685714
("title_time", titles[1], r_client.set)
686715
]
687716
if verbose:
688-
print(("Saving resource allocation image for " +
689-
f" software: {sname}" +
690-
f" version: {version}" +
691-
f" command: {cname}" +
692-
f" column name: {col_name}"))
717+
print(
718+
("Saving resource allocation image for\n" +
719+
f" software: {sname}\n" +
720+
f" version: {version}\n" +
721+
f" command: {cname}\n" +
722+
f" column name: {col_name}\n" +
723+
f" {datetime.now().strftime('%b %d %H:%M:%S')}"))
693724

694725
for k, v, f in values:
695726
redis_key = 'resources$#%s$#%s$#%s$#%s:%s' % (
696727
cname, sname, version, col_name, k)
697728
r_client.delete(redis_key)
698729
f(redis_key, v)
730+
731+
if sname not in scommands_allocation:
732+
scommands_allocation[sname] = {}
733+
if version not in scommands_allocation[sname]:
734+
scommands_allocation[sname][version] = {}
735+
if cname not in scommands_allocation[sname][version]:
736+
scommands_allocation[sname][version][cname] = []
737+
scommands_allocation[sname][version][cname].append(
738+
col_name)
739+
740+
redis_key = 'resources:commands'
741+
r_client.set(redis_key, str(scommands_allocation))

qiita_db/util.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2527,7 +2527,7 @@ def _resource_allocation_plot_helper(
25272527
print(f"\t\tFitting best model for {curr}; column {col_name}")
25282528
# 50 - number of maximum iterations, 3 - number of failures we tolerate
25292529
best_model_name, best_model, options = _resource_allocation_calculate(
2530-
df, x_data, y_data, models, curr, col_name, 50, 3)
2530+
df, x_data, y_data, models, curr, col_name, 50, 3, verbose)
25312531
if verbose:
25322532
print(
25332533
f"\t\tSuccessfully chose best model for {curr}; column {col_name}")
@@ -2553,8 +2553,9 @@ def _resource_allocation_plot_helper(
25532553
success_df, failures_df = _resource_allocation_success_failures(
25542554
df, k, a, b, best_model, col_name, curr)
25552555
failures = failures_df.shape[0]
2556-
ax.scatter(failures_df[col_name], failures_df[curr], color='red', s=3,
2557-
label="failures")
2556+
if failures != 0:
2557+
ax.scatter(failures_df[col_name], failures_df[curr], color='red', s=3,
2558+
label="failures")
25582559

25592560
success_df['node_name'].fillna('unknown', inplace=True)
25602561

@@ -2580,7 +2581,7 @@ def _resource_allocation_plot_helper(
25802581

25812582

25822583
def _resource_allocation_calculate(
2583-
df, x, y, models, type_, col_name, depth, tolerance):
2584+
df, x, y, models, type_, col_name, depth, tolerance, verbose):
25842585
"""Helper function for resource allocation plot. Calculates best_model and
25852586
best_result given the models list and x,y data.
25862587
@@ -2621,6 +2622,11 @@ def _resource_allocation_calculate(
26212622
best_failures = np.inf
26222623
best_max = np.inf
26232624
for model_name, model in models.items():
2625+
if verbose:
2626+
print(
2627+
f"\t\t\tCalculating {model_name} for {type_}; "
2628+
f"{col_name} {datetime.now().strftime('%b %d %H:%M:%S')}"
2629+
)
26242630
model_equation = model['equation']
26252631
# start values for binary search, where sl is left, sr is right
26262632
# penalty weight must be positive & non-zero, hence, sl >= 1.
@@ -2763,9 +2769,9 @@ def _resource_allocation_success_failures(df, k, a, b, model, col_name, type_):
27632769
"""
27642770

27652771
x_plot = np.array(df[col_name])
2766-
df[f'c{type_}'] = model(x_plot, k, a, b)
2767-
success_df = df[df[type_] <= df[f'c{type_}']].copy()
2768-
failures_df = df[df[type_] > df[f'c{type_}']].copy()
2772+
y_plot = model(x_plot, k, a, b)
2773+
success_df = df[df[type_] <= y_plot].copy()
2774+
failures_df = df[df[type_] > y_plot].copy()
27692775
return (success_df, failures_df)
27702776

27712777

0 commit comments

Comments
 (0)