Skip to content

Commit 938d1ce

Browse files
committed
refactor: move DIRAC TS WebApp related RPC calls to dedicated service
1 parent c230247 commit 938d1ce

File tree

9 files changed

+235
-367
lines changed

9 files changed

+235
-367
lines changed

src/DIRAC/MonitoringSystem/Client/WebAppClient.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from DIRAC.Core.Base.Client import Client, createClient
55

66

7-
@createClient("MonitoringSystem/WebApp")
7+
@createClient("Monitoring/WebApp")
88
class WebAppClient(Client):
99
"""WebAppClient sets url for the WebAppHandler."""
1010

src/DIRAC/MonitoringSystem/Service/WebAppHandler.py

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,17 @@
88
from DIRAC.Core.DISET.RequestHandler import RequestHandler
99
from DIRAC.Core.Utilities.JEncode import strToIntDict
1010
from DIRAC.Core.Utilities.ObjectLoader import ObjectLoader
11+
from DIRAC.RequestManagementSystem.Client.Operation import Operation
12+
from DIRAC.RequestManagementSystem.Client.Request import Request
13+
from DIRAC.TransformationSystem.Client import TransformationFilesStatus
14+
from DIRAC.WorkloadManagementSystem.Client import JobStatus
1115
from DIRAC.WorkloadManagementSystem.Service.JobPolicy import RIGHT_GET_INFO, JobPolicy
1216

17+
TASKS_STATE_NAMES = ["TotalCreated", "Created"] + sorted(
18+
set(JobStatus.JOB_STATES) | set(Request.ALL_STATES) | set(Operation.ALL_STATES)
19+
)
20+
FILES_STATE_NAMES = ["PercentProcessed", "Total"] + TransformationFilesStatus.TRANSFORMATION_FILES_STATES
21+
1322

1423
class WebAppHandler(RequestHandler):
1524
@classmethod
@@ -27,6 +36,11 @@ def initializeHandler(cls, serviceInfoDict):
2736
return result
2837
cls.jobDB = result["Value"](parentLogger=cls.log)
2938

39+
result = ObjectLoader().loadObject("TransformationSystem.DB.TransformationDB", "TransformationDB")
40+
if not result["OK"]:
41+
return result
42+
cls.transformationDB = result["Value"](parentLogger=cls.log)
43+
3044
except RuntimeError as excp:
3145
return S_ERROR(f"Can't connect to DB: {excp}")
3246

@@ -320,3 +334,198 @@ def export_getSiteSummarySelectors(cls):
320334
resultDict["Site"] = siteList
321335

322336
return S_OK(resultDict)
337+
338+
##############################################################################
339+
# Transformations
340+
##############################################################################
341+
342+
types_getDistinctAttributeValues = [str, dict]
343+
344+
@classmethod
345+
def export_getDistinctAttributeValues(cls, attribute, selectDict):
346+
res = cls.transformationDB.getTableDistinctAttributeValues("Transformations", [attribute], selectDict)
347+
if not res["OK"]:
348+
return res
349+
return S_OK(res["Value"][attribute])
350+
351+
types_getTransformationFilesSummaryWeb = [dict, list, int, int]
352+
353+
def export_getTransformationFilesSummaryWeb(cls, selectDict, sortList, startItem, maxItems):
354+
selectColumns = (["TransformationID", "Status", "UsedSE", "TargetSE"],)
355+
timeStamp = ("LastUpdate",)
356+
statusColumn = ("Status",)
357+
fromDate = selectDict.get("FromDate", None)
358+
if fromDate:
359+
del selectDict["FromDate"]
360+
# if not fromDate:
361+
# fromDate = last_update
362+
toDate = selectDict.get("ToDate", None)
363+
if toDate:
364+
del selectDict["ToDate"]
365+
# Sorting instructions. Only one for the moment.
366+
if sortList:
367+
orderAttribute = sortList[0][0] + ":" + sortList[0][1]
368+
else:
369+
orderAttribute = None
370+
# Get the columns that match the selection
371+
fcn = None
372+
fcnName = "getTransformationFiles"
373+
if hasattr(cls.transformationDB, fcnName) and callable(getattr(cls.transformationDB, fcnName)):
374+
fcn = getattr(cls.transformationDB, fcnName)
375+
if not fcn:
376+
return S_ERROR(f"Unable to invoke gTransformationDB.{fcnName}, it isn't a member function")
377+
res = fcn(condDict=selectDict, older=toDate, newer=fromDate, timeStamp=timeStamp, orderAttribute=orderAttribute)
378+
if not res["OK"]:
379+
return res
380+
381+
# The full list of columns in contained here
382+
allRows = res["Value"]
383+
# Prepare the standard structure now within the resultDict dictionary
384+
resultDict = {}
385+
# Create the total records entry
386+
resultDict["TotalRecords"] = len(allRows)
387+
388+
# Get the rows which are within the selected window
389+
if resultDict["TotalRecords"] == 0:
390+
return S_OK(resultDict)
391+
ini = startItem
392+
last = ini + maxItems
393+
if ini >= resultDict["TotalRecords"]:
394+
return S_ERROR("Item number out of range")
395+
if last > resultDict["TotalRecords"]:
396+
last = resultDict["TotalRecords"]
397+
398+
selectedRows = allRows[ini:last]
399+
resultDict["Records"] = []
400+
for row in selectedRows:
401+
resultDict["Records"].append(list(row.values()))
402+
403+
# Create the ParameterNames entry
404+
resultDict["ParameterNames"] = list(selectedRows[0].keys())
405+
# Find which element in the tuple contains the requested status
406+
if statusColumn not in resultDict["ParameterNames"]:
407+
return S_ERROR("Provided status column not present")
408+
409+
# Generate the status dictionary
410+
statusDict = {}
411+
for row in selectedRows:
412+
status = row[statusColumn]
413+
statusDict[status] = statusDict.setdefault(status, 0) + 1
414+
resultDict["Extras"] = statusDict
415+
416+
# Obtain the distinct values of the selection parameters
417+
res = cls.transformationDB.getTableDistinctAttributeValues(
418+
"TransformationFiles", selectColumns, selectDict, older=toDate, newer=fromDate
419+
)
420+
distinctSelections = zip(selectColumns, [])
421+
if res["OK"]:
422+
distinctSelections = res["Value"]
423+
resultDict["Selections"] = distinctSelections
424+
425+
return S_OK(resultDict)
426+
427+
types_getTransformationSummaryWeb = [dict, list, int, int]
428+
429+
def export_getTransformationSummaryWeb(cls, selectDict, sortList, startItem, maxItems):
430+
"""Get the summary of the transformation information for a given page in the generic format"""
431+
432+
# Obtain the timing information from the selectDict
433+
last_update = selectDict.get("CreationDate", None)
434+
if last_update:
435+
del selectDict["CreationDate"]
436+
fromDate = selectDict.get("FromDate", None)
437+
if fromDate:
438+
del selectDict["FromDate"]
439+
if not fromDate:
440+
fromDate = last_update
441+
toDate = selectDict.get("ToDate", None)
442+
if toDate:
443+
del selectDict["ToDate"]
444+
# Sorting instructions. Only one for the moment.
445+
if sortList:
446+
orderAttribute = []
447+
for i in sortList:
448+
orderAttribute += [i[0] + ":" + i[1]]
449+
else:
450+
orderAttribute = None
451+
452+
# Get the transformations that match the selection
453+
res = cls.transformationDB.getTransformations(
454+
condDict=selectDict, older=toDate, newer=fromDate, orderAttribute=orderAttribute
455+
)
456+
if not res["OK"]:
457+
return res
458+
459+
ops = Operations()
460+
# Prepare the standard structure now within the resultDict dictionary
461+
resultDict = {}
462+
trList = res["Records"]
463+
# Create the total records entry
464+
nTrans = len(trList)
465+
resultDict["TotalRecords"] = nTrans
466+
# Create the ParameterNames entry
467+
# As this list is a reference to the list in the DB, we cannot extend it, therefore copy it
468+
resultDict["ParameterNames"] = list(res["ParameterNames"])
469+
# Add the job states to the ParameterNames entry
470+
taskStateNames = TASKS_STATE_NAMES + ops.getValue("Transformations/AdditionalTaskStates", [])
471+
resultDict["ParameterNames"] += ["Jobs_" + x for x in taskStateNames]
472+
# Add the file states to the ParameterNames entry
473+
fileStateNames = FILES_STATE_NAMES + ops.getValue("Transformations/AdditionalFileStates", [])
474+
resultDict["ParameterNames"] += ["Files_" + x for x in fileStateNames]
475+
476+
# Get the transformations which are within the selected window
477+
if nTrans == 0:
478+
return S_OK(resultDict)
479+
ini = startItem
480+
last = ini + maxItems
481+
if ini >= nTrans:
482+
return S_ERROR("Item number out of range")
483+
if last > nTrans:
484+
last = nTrans
485+
transList = trList[ini:last]
486+
487+
statusDict = {}
488+
extendableTranfs = ops.getValue("Transformations/ExtendableTransfTypes", ["Simulation", "MCsimulation"])
489+
givenUpFileStatus = ops.getValue("Transformations/GivenUpFileStatus", ["MissingInFC"])
490+
problematicStatuses = ops.getValue("Transformations/ProblematicStatuses", ["Problematic"])
491+
# Add specific information for each selected transformation
492+
for trans in transList:
493+
transDict = dict(zip(resultDict["ParameterNames"], trans))
494+
495+
# Update the status counters
496+
status = transDict["Status"]
497+
statusDict[status] = statusDict.setdefault(status, 0) + 1
498+
499+
# Get the statistics on the number of jobs for the transformation
500+
transID = transDict["TransformationID"]
501+
res = cls.transformationDB.getTransformationTaskStats(transID)
502+
taskDict = {}
503+
if res["OK"] and res["Value"]:
504+
taskDict = res["Value"]
505+
for state in taskStateNames:
506+
trans.append(taskDict.get(state, 0))
507+
508+
# Get the statistics for the number of files for the transformation
509+
fileDict = {}
510+
transType = transDict["Type"]
511+
if transType.lower() in extendableTranfs:
512+
fileDict["PercentProcessed"] = "-"
513+
else:
514+
res = cls.transformationDB.getTransformationStats(transID)
515+
if res["OK"]:
516+
fileDict = res["Value"]
517+
total = fileDict["Total"]
518+
for stat in givenUpFileStatus:
519+
total -= fileDict.get(stat, 0)
520+
processed = fileDict.get(TransformationFilesStatus.PROCESSED, 0)
521+
fileDict["PercentProcessed"] = f"{int(processed * 1000.0 / total) / 10.0:.1f}" if total else 0.0
522+
problematic = 0
523+
for stat in problematicStatuses:
524+
problematic += fileDict.get(stat, 0)
525+
fileDict["Problematic"] = problematic
526+
for state in fileStateNames:
527+
trans.append(fileDict.get(state, 0))
528+
529+
resultDict["Records"] = transList
530+
resultDict["Extras"] = statusDict
531+
return S_OK(resultDict)

src/DIRAC/ProductionSystem/scripts/dirac_prod_get_trans.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,13 @@ def main():
1616
Script.registerArgument("prodID: Production ID")
1717
_, args = Script.parseCommandLine()
1818

19+
from DIRAC.MonitoringSystem.Client.WebAppClient import WebAppClient
1920
from DIRAC.ProductionSystem.Client.ProductionClient import ProductionClient
20-
from DIRAC.TransformationSystem.Client.TransformationClient import TransformationClient
2121

2222
# get arguments
2323
prodID = args[0]
2424

2525
prodClient = ProductionClient()
26-
transClient = TransformationClient()
2726

2827
res = prodClient.getProductionTransformations(prodID)
2928
transIDs = []
@@ -70,7 +69,7 @@ def main():
7069
]
7170
resList = []
7271

73-
res = transClient.getTransformationSummaryWeb({"TransformationID": transIDs}, [], 0, len(transIDs))
72+
res = WebAppClient().getTransformationSummaryWeb({"TransformationID": transIDs}, [], 0, len(transIDs))
7473

7574
if not res["OK"]:
7675
DIRAC.gLogger.error(res["Message"])

src/DIRAC/TransformationSystem/Client/Transformation.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from DIRAC.Core.Base.API import API
1010
from DIRAC.Core.Utilities.JEncode import encode
1111
from DIRAC.Core.Utilities.PromptUser import promptUser
12+
from DIRAC.MonitoringSystem.Client.WebAppClient import WebAppClient
1213
from DIRAC.RequestManagementSystem.Client.Operation import Operation
1314
from DIRAC.TransformationSystem.Client.BodyPlugin.BaseBody import BaseBody
1415
from DIRAC.TransformationSystem.Client.TransformationClient import TransformationClient
@@ -498,7 +499,7 @@ def getSummaryTransformations(self, transID=[]):
498499
]
499500
dictList = []
500501

501-
result = self.transClient.getTransformationSummaryWeb(condDict, orderby, start, maxitems)
502+
result = WebAppClient().getTransformationSummaryWeb(condDict, orderby, start, maxitems)
502503
if not result["OK"]:
503504
self._prettyPrint(result)
504505
return result

src/DIRAC/TransformationSystem/Client/TransformationClient.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,6 @@ class TransformationClient(Client):
4848
4949
getFileSummary(lfns)
5050
exists(lfns)
51-
52-
Web monitoring tools
53-
54-
getDistinctAttributeValues(attribute, selectDict)
55-
getTransformationStatusCounters()
56-
getTransformationSummary()
57-
getTransformationSummaryWeb(selectDict, sortList, startItem, maxItems)
5851
"""
5952

6053
def __init__(self, **kwargs):

0 commit comments

Comments
 (0)