# File lib/ruote/dboard/process_status.rb, line 546
    def self.fetch(context, wfids, opts)

      swfids = wfids.collect { |wfid| /!#{wfid}-\d+$/ }

      batch = { 'id' => "#{Thread.current.object_id}-#{Time.now.to_f}" }
        #
        # some storages may optimize when they can distinguish
        # which get_many fit in the same batch...

      exps = context.storage.get_many(
        'expressions', wfids, :batch => batch).compact
      swis = context.storage.get_many(
        'workitems', wfids, :batch => batch).compact
      errs = context.storage.get_many(
        'errors', wfids, :batch => batch).compact
      schs = context.storage.get_many(
        'schedules', swfids, :batch => batch).compact
          #
          # some slow storages need the compaction... couch...

      errs = errs.collect { |err| ProcessError.new(err) }
      schs = schs.collect { |sch| Ruote.schedule_to_h(sch) }

      by_wfid = {}
      as = lambda { [ [], [], [], [], [] ] }

      exps.each { |exp| (by_wfid[exp['fei']['wfid']]  ||= as.call)[0] << exp }
      swis.each { |swi| (by_wfid[swi['fei']['wfid']]  ||= as.call)[1] << swi }
      errs.each { |err| (by_wfid[err.wfid]            ||= as.call)[2] << err }
      schs.each { |sch| (by_wfid[sch['wfid']]         ||= as.call)[3] << sch }
      # TODO: trackers

      wfids = by_wfid.keys.sort
      wfids = wfids.reverse if opts[:descending]
        # re-adjust list of wfids, only take what was found

      wfids.collect { |wfid|
        info = by_wfid[wfid]
        info ? self.new(context, *info) : nil
      }.compact
    end