मैं यह कैसे सुनिश्चित कर सकता हूं कि एक नौकरी दो बार बुल में नहीं चलती है?


11

मेरे पास दो कार्य हैं, scheduleScan()और scan()

scan()scheduleScan() जब कोई नया स्कैन शेड्यूल करने के अलावा और कुछ नहीं होता है , तो कॉल scheduleScan()कर सकते हैं scan()। लेकिन एक समस्या है, कुछ नौकरियां दो बार चलती हैं।

मैं यह सुनिश्चित करना चाहता हूं कि किसी भी समय केवल एक ही कार्य संसाधित किया जा रहा है। मैं उसे कैसे प्राप्त कर सकता हूं? मेरा मानना ​​है कि इसके साथ कुछ करना है done(), (यह स्कैन में था), अब हटा दिया गया है, लेकिन मैं एक समाधान के साथ नहीं आ सका।

बैल संस्करण: 3.12.1

महत्वपूर्ण देर से संपादित: scan() दूसरे कार्यों को कॉल करता है और वे अन्य कार्यों को कॉल कर सकते हैं या नहीं भी कर सकते हैं, लेकिन वे सभी सिंक फ़ंक्शन हैं, इसलिए वे केवल एक फ़ंक्शन को कॉल करते हैं जब उनके स्वयं के काम पूरे हो जाते हैं, केवल एक ही रास्ता है। "ट्री" के अंत में, मैं इसे कॉल करता हूं, अंतिम फ़ंक्शन शेड्यूलस्कैन () कहता है, लेकिन दो एक साथ चलने वाले काम नहीं हो सकते हैं। हर एक काम शुरू होता है scan(), वैसे, और वे समाप्त हो जाते हैंscheduleScan(stock, period, milliseconds, 'called by file.js')

export function update(job) {
  // does some calculations, then it may call scheduleScan() or
  // it may call another function, and that could be the one calling
  // scheduleScan() function.
  // For instance, a function like finalize()
}

export function scan(job) {
  update(job)
}


import moment from 'moment'
import stringHash from 'string-hash'
const opts = { redis: { port: 6379, host: '127.0.0.1', password: mypassword' } }
let queue = new Queue('scan', opts)

queue.process(1, (job) => {
  job.progress(100).then(() => {
    scan(job)
  })
})

export function scheduleScan (stock, period, milliseconds, triggeredBy) {
  let uniqueId = stringHash(stock + ':' + period)

  queue.getJob(uniqueId).then(job => {
    if (!job) {
      if (milliseconds) {
        queue.add({ stock, period, triggeredBy }, { delay: milliseconds, jobId: uniqueId }).then(() => {
          // console.log('Added with ms: ' + stock + ' ' + period)
        }).catch(err => {
          if (err) {
            console.log('Can not add because it exists ' + new Date())
          }
        })
      } else {
        queue.add({ stock, period, triggeredBy }, { jobId: uniqueId }).then(() => {
          // console.log('Added without ms: ' + stock + ' ' + period)
        }).catch(err => {
          if (err) {
            console.log('Can not add because it exists ' + new Date())
          }
        })
      }
    } else {
      job.getState().then(state => {
        if (state === 'completed') {
          job.remove().then(() => {
            if (milliseconds) {
              queue.add({ stock, period, triggeredBy }, { delay: milliseconds, jobId: uniqueId }).then(() => {
                // console.log('Added with ms: ' + stock + ' ' + period)
              }).catch(err => {
                if (err) {
                  console.log('Can not add because it exists ' + new Date())
                }
              })
            } else {
              queue.add({ stock, period, triggeredBy }, { jobId: uniqueId }).then(() => {
                // console.log('Added without ms: ' + stock + ' ' + period)
              }).catch(err => {
                if (err) {
                  console.log('Can not add because it exists ' + new Date())
                }
              })
            }
          }).catch(err => {
            if (err) {
              // console.log(err)
            }
          })
        }
      }).catch(err => {
        // console.log(err)
      })
    }
  })
}

मैं scanफ़ंक्शन खोजने में असमर्थ हूं , क्या आप मदद कर सकते हैं?
मुहम्मद जीशान 20

@MuhammadZeeshan मैंने इसे जोड़ा, मेरी गलती है।
सैलीप

जवाबों:


6

समस्या, मेरा मानना ​​है कि आपका scanकार्य async है। तो आपका job.progressफ़ंक्शन कॉल करता है scanऔर फिर तुरंत कॉल doneकरके कतार को किसी अन्य कार्य को संसाधित करने की अनुमति देता है।

एक समाधान doneआपके scanऔर scheduleScanकार्यों के लिए एक पैरामीटर के रूप में कॉलबैक को पारित करने के लिए हो सकता है , और जब आप अपनी नौकरी (या त्रुटि) पूरी कर लेते हैं, तो इसे लागू कर सकते हैं।

एक और (बेहतर) समाधान यह सुनिश्चित करने के लिए हो सकता है कि आप हमेशा एक Promiseसे लौटें scanऔर scheduleScan, फिर हल करने के वादे का इंतजार करें और फिर फोन करें done। यदि ऐसा कर रहे हैं, तो सुनिश्चित करें कि आप अपने scheduleScanफ़ंक्शन में अपने सभी वादों की वापसी की श्रृंखला बनाते हैं ।

queue.process(1, (job, done) => {
  job.progress(100).then(() => {
    scan(job)
        .then(done)
        .catch(done)
  })
})

export function scan() {
   // business logic
   return scheduleScan()
}

// Chain all of your promise returns. Otherwise
// the scan function will return sooner and allow done to be called
// prior to the scheduleScan function finishing it's execution
export function scheduleScan() {
    return queue.getJob(..).then(() => {
        ....
        return queue.add()...
        ....
        return queue.add(...)
            .catch(e => {
                 console.log(e);
                 // propogate errors!
                 throw e;
             })

}

मैंने अपना प्रश्न संपादित कर लिया है, क्या आप इसे फिर से जांच सकते हैं, विशेष रूप से "महत्वपूर्ण देर से संपादित" भाग? क्या आपका जवाब अभी भी इस स्थिति में लागू होता है? धन्यवाद।
12

1
हां, यह अभी भी मान्य है। आपके संपादन से, मुझे लगता है कि आप कह रहे हैं कि scheduledScanहमेशा अन्य सभी सिंक कार्यों के बाद कहा जाता है scan। अगर ऐसा है, तो हाँ, मेरा जवाब अभी भी मान्य है। बस हमेशा वादा है कि से लौटाया नहीं जाएगा लौटने scheduleScanमें scanसमारोह
जीव्स

फिर, मेरी गलती। पहला फ़ंक्शन, अपडेट (), स्कैन में है, लेकिन अपडेट () अंतिम रूप से दूसरे फ़ंक्शन () को कॉल कर सकता है, और अंतिम रूप दे सकता है () शेड्यूलस्कन () को कॉल कर सकता है। कृपया ध्यान रखें कि ये एक क्रम में होते हैं, इसलिए एक से अधिक कॉल नहीं होते हैं, मैं अपना ऐप मॉड्यूलर रखने के लिए ऐसा कर रहा हूं। - धन्यवाद
नमकीन

1
हां, वही जवाब। यदि updateकॉल scheduledScanया उनके बीच किसी भी संख्या में फ़ंक्शन। मुख्य बिंदु यह है कि आपको फ़ंक्शन scheduleScanसे वापस सभी प्रकार से वादा श्रृंखला वापस करने की आवश्यकता scanहै। तो अगर scanकॉल करता है updateजो कॉल करता है finalise..... कौन scheduleScanसे वादे की श्रृंखला को सभी फ़ंक्शन इनवोकेशन के माध्यम से वापस करने की आवश्यकता होगी, अर्थात बस सुनिश्चित करें कि आप इनमें से प्रत्येक फ़ंक्शन से वादा वापस करते हैं।
जीव्स

तो बस मेरी पिछली टिप्पणी को स्पष्ट करने के लिए। उदाहरण के लिए, यदि स्कैन के अंदर आप अपडेट को कॉल करते हैं। आपको स्कैन फ़ंक्शन से अपडेट (एक वादा) के परिणाम को वापस करने की आवश्यकता है।
जीव्स

4

स्कैन फ़ंक्शन एक एसिंक्रोनस फ़ंक्शन है। आपके queue.process()फ़ंक्शन में आपको स्कैन फ़ंक्शन का इंतजार करना होगा और फिर done()कॉलबैक कॉल करना होगा ।

export async function scan(job) {
  // it does some calculations, then it creates a new schedule.
  return scheduleScan(stock, period, milliseconds, "scan.js");
}

queue.process(1, (job, done) => {
  job.progress(100).then(async() => {
    await scan(job);
    done();
  });
});

export async function scheduleScan(stock, period, milliseconds, triggeredBy) {
    let uniqueId = stringHash(stock + ":" + period);
    try {
      const existingJob = await queue.getJob(uniqueId);
      if (!existingJob) {
        const job = await addJob({
          queue,
          stock,
          period,
          uniqueId,
          milliseconds,
          triggeredBy
        });
        return job;
      } else {
        const jobState = await existingJob.getState();
        if (jobState === "completed") {
          await existingJob.remove();
          const newJob = await addJob({
            queue,
            stock,
            period,
            uniqueId,
            milliseconds,
            triggeredBy
          });
          return newJob;
        }
      }
    } catch (err) {
      throw new Error(err);
    }
}

export function addJob({ queue, stock, period, milliseconds, triggeredBy }) {
  if (milliseconds) {
    return queue.add(
      { stock, period, triggeredBy },
      { delay: milliseconds, jobId: uniqueId }
    );
  } else {
    return queue.add({ stock, period, triggeredBy }, { jobId: uniqueId });
  }
}

इसे इस्तेमाल करे! मैंने async-wait का उपयोग करके कोड को थोड़ा रीफ़ैक्टर करने की कोशिश की है।


मैंने अपना प्रश्न संपादित कर लिया है, क्या आप इसे फिर से जांच सकते हैं, विशेष रूप से "महत्वपूर्ण देर से संपादित" भाग? क्या आपका जवाब अभी भी इस स्थिति में लागू होता है? धन्यवाद।
12
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.