Repository: dmwm/wmcore
Issue: MSOutput - unhandled exception in _getDatasetSize()

**Impact of the bug**
MSOutput

**Describe the bug**
While trying to determine dataset size if the service for any reason fails to do so (e.g. fails to get DID info from Rucios etc.) we do not handle the exception [1] but just let it reach the upper level pipeline exception handler, while proper actions  should be taken at place. In result we pollute the logs with exceptions, which in many cases could be just predictable/expected behavior.   


[1]
https://github.com/dmwm/WMCore/blob/e45a4425c5437d194d0d02814b7011c752c33548/src/python/WMCore/MicroService/MSOutput/MSOutput.py#L696

[2]
```
2021-03-23 01:14:48,521:ERROR:MSOutput: MSOutputProducer Pipeline Possibly broken read from ReqMgr2 API or other. Err: 'bytes'. Continue to the next document.
Traceback (most recent call last):
  File "/data/srv/HG2103g/sw/slc7_amd64_gcc630/cms/reqmgr2ms/0.4.6.pre9/lib/python2.7/site-packages/WMCore/MicroService/Unified/MSOutput.py", line 545, in msOutputProducer
    msPipeline.run(request)
  File "/data/srv/HG2103g/sw/slc7_amd64_gcc630/cms/reqmgr2ms/0.4.6.pre9/lib/python2.7/site-packages/Utils/Pipeline.py", line 140, in run
    return reduce(lambda obj, functor: functor(obj), self.funcLine, obj)
  File "/data/srv/HG2103g/sw/slc7_amd64_gcc630/cms/reqmgr2ms/0.4.6.pre9/lib/python2.7/site-packages/Utils/Pipeline.py", line 140, in <lambda>
    return reduce(lambda obj, functor: functor(obj), self.funcLine, obj)
  File "/data/srv/HG2103g/sw/slc7_amd64_gcc630/cms/reqmgr2ms/0.4.6.pre9/lib/python2.7/site-packages/Utils/Pipeline.py", line 72, in __call__
    return self.run(obj)
  File "/data/srv/HG2103g/sw/slc7_amd64_gcc630/cms/reqmgr2ms/0.4.6.pre9/lib/python2.7/site-packages/Utils/Pipeline.py", line 75, in run
    return self.func(obj, *self.args, **self.kwargs)
  File "/data/srv/HG2103g/sw/slc7_amd64_gcc630/cms/reqmgr2ms/0.4.6.pre9/lib/python2.7/site-packages/WMCore/MicroService/Unified/MSOutput.py", line 622, in docInfoUpdate
    bytesSize = self._getDatasetSize(dataItem['Dataset'])
  File "/data/srv/HG2103g/sw/slc7_amd64_gcc630/cms/reqmgr2ms/0.4.6.pre9/lib/python2.7/site-packages/WMCore/MicroService/Unified/MSOutput.py", line 695, in _getDatasetSize
    return didInfo["bytes"]
KeyError: 'bytes'
```

**How to reproduce it**
Just look at the MSOutput  logs

**Expected behavior**
In case the situation is expected, we should handle the exception at the place where it happens (even if we need to create a new class of exceptions), and propagate only the unexpected ones upstream.
 
**Additional context and error message**
N/A


Changed files:
src/python/WMCore/MicroService/MSOutput/MSOutput.py

diff --git a/src/python/WMCore/MicroService/MSOutput/MSOutput.py b/src/python/WMCore/MicroService/MSOutput/MSOutput.py
index 26816bddd..0aab957f8 100644
--- a/src/python/WMCore/MicroService/MSOutput/MSOutput.py
+++ b/src/python/WMCore/MicroService/MSOutput/MSOutput.py
@@ -797,11 +797,11 @@ class MSOutput(MSCore):
 
     def canDatasetGoToTape(self, dataItem, workflow):
         """
-        This function evaluates whether a dataset can be passed to the
+        This function evaluates whether a container can be passed to the
         Data Management system, considering the following configurations:
-          1) list of blacklisted tiers in the MicroService configuration
-          2) list of white listed tiers bypassing the Unified configuration
-          3) list of black and white listed tiers in the Unified config
+          1) list of tiers banned in the MicroService configuration
+          2) list of tiers allowed to bypass the Unified configuration
+          3) list of allowed and banned tiers in the Unified config
         :param dataItem: output map dictionary present in the MongoDB record
         :param workflow: MSOutputTemplate object retrieved from MongoDB
         :return: True if the dataset is allowed to pass, False otherwise
@@ -816,6 +816,9 @@ class MSOutput(MSCore):
         if workflow['RequestType'] == "Resubmission":
             # their parent/original workflow will take care of all the data placement
             return False
+        if int(dataItem['DatasetSize']) == 0:
+            # container hasn't been produced in the workflow
+            return False
 
         if dataItem['TapeRuleID']:
             msg = "Output dataset: {} from workflow: {} ".format(dataItem['Dataset'], workflow['RequestName'])