ฉันมีสองโมดูล module_alpha และ module_beta
ทั้งสองโมดูลติดตั้งตารางฐานข้อมูลด้วย hook_schema()
ซึ่งใช้ในการติดตามข้อมูลเกี่ยวกับโหนดที่เผยแพร่ ข้อมูลถูกบันทึกในตารางด้วยวิธีการบริการที่ดำเนินการจาก hook_node_insert()
และ hook_node_update()
ตะขอ ทั้งหมดนี้ใช้งานได้
แต่ฉันต้องประมวลผลโหนดที่มีอยู่ทั้งหมดเมื่อติดตั้งโมดูลเพื่อทดแทนตารางที่กำหนดเองด้วยข้อมูลเกี่ยวกับโหนดที่เผยแพร่ที่มีอยู่แล้วแต่ละโมดูลดำเนินการ hook_install()
และใช้กระบวนการแบบแบตช์เพื่อประมวลผลโหนดที่เผยแพร่ที่มีอยู่ทั้งหมด อย่างไรก็ตาม ฉันเห็นความไม่ลงรอยกันแปลกๆ บางครั้งกระบวนการแบทช์ดำเนินการ บางครั้งก็ไม่ทำงาน สถานการณ์จำลองอาจใช้ได้กับโมดูลหนึ่ง แต่โมดูลอื่นใช้ไม่ได้ ทั้งหมดนี้แม้ว่ารหัสจะเหมือนกันเกือบทั้งหมด นี่คือสถานการณ์ที่ฉันได้ทดสอบ:
วิธีการติดตั้งโมดูล |
โมดูลอัลฟ่า |
โมดูลเบต้า |
drush ใน MYMODULE |
ชุดดำเนินการ |
ชุดงานไม่ดำเนินการ |
ซิม |
ชุดงานไม่ดำเนินการ |
ชุดงานไม่ดำเนินการ |
UI เปิดใช้งานโมดูลจาก /admin/modules |
ชุดดำเนินการ |
ชุดดำเนินการ |
UI, ซิงค์การกำหนดค่าจาก /admin/config/development/configuration |
ชุดดำเนินการ |
ชุดดำเนินการ |
การดำเนินการเป็นชุดบ่งชี้ว่าชุดดำเนินการอย่างสมบูรณ์ตามที่คาดไว้ พร้อมข้อความแสดงความคืบหน้า และตารางของฉันเต็มไปด้วยข้อมูล แบทช์ไม่ดำเนินการ บ่งชี้ว่าแบทช์ไม่ถูกดำเนินการเลย ไม่มีข้อความแสดงข้อผิดพลาดแสดงหรือในบันทึก ส่วนที่แปลกประหลาดที่สุดเกี่ยวกับข้อมูลนี้คือ drush และ module_alpha
ประสบความสำเร็จเสมอและ drush และ module_beta
ล้มเหลวเสมอ
อะไรเป็นสาเหตุให้กระบวนการแบทช์ทำงานได้ในบางกรณี แต่ไม่ใช่ในบางกรณี ฉันจะดำเนินการกระบวนการแบทช์นี้อย่างสม่ำเสมอในทั้ง 4 วิธีเหล่านี้ได้อย่างไร ไม่ว่าจะเปิดใช้งานโมดูลผ่าน UI หรือ drush พูดตามตรง วิธีเดียวที่ฉันจะใช้คือ ซิม
รหัส:
ใน MYMODULE.install:
ฟังก์ชัน MYMODULE_install() {
$batch = ใหม่ \Drupal\Core\Batch\BatchBuilder();
$แบทช์
->setTitle(t('กำลังประมวลผลรายการที่มีอยู่จำนวนมาก'))
// การดำเนินการนี้อ้างอิงถึงฟังก์ชันที่แตกต่างกันในแต่ละโมดูล
// ในทั้งสองกรณี ฟังก์ชันจะอยู่ใน MYMODULE.module และโค้ดเกือบจะเหมือนกัน
->addOperation('_MYMODULE_initialize_items', []);
batch_set($batch->toArray());
}
ใน MYMODULE.module:
ฟังก์ชัน _MYMODULE_initialize_items(&$บริบท) {
$batch_size = 25;
$entity_type = 'โหนด';
// ฉันกำหนดเป้าหมายบันเดิลที่แตกต่างกันใน module_alpha และ module_beta
$มัด = 'MY_TARGET_BUNDLE';
ถ้า (!isset($context['sandbox']['ประมวลผล'])) {
$context['sandbox']['ประมวลผลแล้ว'] = 0;
}
ถ้า (ว่าง ($context['sandbox']['entity_ids'])) {
$context['sandbox']['entity_ids'] = \Drupal::entityTypeManager()
->getStorage($entity_type)
->getQuery()
->condition('ประเภท', $bundle)
->เงื่อนไข ('สถานะ', 1)
->ดำเนินการ ();
ถ้า (is_array($context['sandbox']['entity_ids'])) {
$context['sandbox']['total'] = count($context['sandbox']['entity_ids']);
}
}
ถ้า (!empty($context['sandbox']['entity_ids'])) {
$current_batch_ids = array_slice($context['sandbox']['entity_ids'], $context['sandbox']['processed'], $batch_size);
$current_batch_entities = \Drupal::entityTypeManager()
->getStorage($entity_type)
->loadMultiple($current_batch_ids);
foreach ($current_batch_entities เป็น $entity) {
// ฉันใช้บริการและวิธีการอื่นใน module_alpha และ module_beta
\Drupal::service('MYMODULE.my_service')
->processEntity($เอนทิตี);
$context['sandbox']['ประมวลผล']++;
}
}
ถ้า (!empty($context['sandbox']['total'])) {
$context['finished'] = $context['sandbox']['processed'] / $context['sandbox']['total'];
$context['message'] = t('ประมวลผล @ประมวลผล จาก @total items.', [
'@processed' => $context['sandbox']['ประมวลผล'],
'@total' => $context['sandbox']['total'],
]);
}
อื่น {
$context['เสร็จสิ้น'] = 1;
}
}
ตัวอย่างวิธีการบริการที่เรียกใช้ในกระบวนการแบทช์:
ฟังก์ชั่นสาธารณะ processEntity (EntityInterface $entity) {
// $this->db ถูกฉีดบริการ `@database` เช่น \Drupal::service('database');
ส่งคืน $this->db
->แทรก('MYMODULE_mytable')
->ฟิลด์ ([
'entity_type' => $entity->getEntityTypeId(),
'entity_bundle' => $entity->bundle(),
'entity_uuid' => $entity->uuid(),
// ฯลฯ...
])
->ดำเนินการ ();
}