Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/nuance/worker/NuanceItemUpdateWorker.php
12256 views
1
<?php
2
3
final class NuanceItemUpdateWorker
4
extends NuanceWorker {
5
6
protected function doWork() {
7
$item_phid = $this->getTaskDataValue('itemPHID');
8
9
$lock = $this->newLock($item_phid);
10
11
$lock->lock(1);
12
try {
13
$item = $this->loadItem($item_phid);
14
$this->updateItem($item);
15
$this->routeItem($item);
16
$this->applyCommands($item);
17
} catch (Exception $ex) {
18
$lock->unlock();
19
throw $ex;
20
}
21
22
$lock->unlock();
23
}
24
25
private function updateItem(NuanceItem $item) {
26
$impl = $item->getImplementation();
27
if (!$impl->canUpdateItems()) {
28
return null;
29
}
30
31
$viewer = $this->getViewer();
32
33
$impl->setViewer($viewer);
34
$impl->updateItem($item);
35
}
36
37
private function routeItem(NuanceItem $item) {
38
$status = $item->getStatus();
39
if ($status != NuanceItem::STATUS_ROUTING) {
40
return;
41
}
42
43
$source = $item->getSource();
44
45
// For now, always route items into the source's default queue.
46
47
$item
48
->setQueuePHID($source->getDefaultQueuePHID())
49
->setStatus(NuanceItem::STATUS_OPEN)
50
->save();
51
}
52
53
private function applyCommands(NuanceItem $item) {
54
$viewer = $this->getViewer();
55
56
$commands = id(new NuanceItemCommandQuery())
57
->setViewer($viewer)
58
->withItemPHIDs(array($item->getPHID()))
59
->withStatuses(
60
array(
61
NuanceItemCommand::STATUS_ISSUED,
62
))
63
->execute();
64
$commands = msort($commands, 'getID');
65
66
$this->executeCommandList($item, $commands);
67
}
68
69
public function executeCommands(NuanceItem $item, array $commands) {
70
if (!$commands) {
71
return true;
72
}
73
74
$item_phid = $item->getPHID();
75
$viewer = $this->getViewer();
76
77
$lock = $this->newLock($item_phid);
78
try {
79
$lock->lock(1);
80
} catch (PhutilLockException $ex) {
81
return false;
82
}
83
84
try {
85
$item = $this->loadItem($item_phid);
86
87
// Reload commands now that we have a lock, to make sure we don't
88
// execute any commands twice by mistake.
89
$commands = id(new NuanceItemCommandQuery())
90
->setViewer($viewer)
91
->withIDs(mpull($commands, 'getID'))
92
->execute();
93
94
$this->executeCommandList($item, $commands);
95
} catch (Exception $ex) {
96
$lock->unlock();
97
throw $ex;
98
}
99
100
$lock->unlock();
101
102
return true;
103
}
104
105
private function executeCommandList(NuanceItem $item, array $commands) {
106
$viewer = $this->getViewer();
107
108
$executors = NuanceCommandImplementation::getAllCommands();
109
foreach ($commands as $command) {
110
if ($command->getItemPHID() !== $item->getPHID()) {
111
throw new Exception(
112
pht('Trying to apply a command to the wrong item!'));
113
}
114
115
if ($command->getStatus() !== NuanceItemCommand::STATUS_ISSUED) {
116
// Never execute commands which have already been issued.
117
continue;
118
}
119
120
$command
121
->setStatus(NuanceItemCommand::STATUS_EXECUTING)
122
->save();
123
124
try {
125
$command_key = $command->getCommand();
126
127
$executor = idx($executors, $command_key);
128
if (!$executor) {
129
throw new Exception(
130
pht(
131
'Unable to execute command "%s": this command does not have '.
132
'a recognized command implementation.',
133
$command_key));
134
}
135
136
$executor = clone $executor;
137
138
$executor
139
->setActor($viewer)
140
->applyCommand($item, $command);
141
142
$command
143
->setStatus(NuanceItemCommand::STATUS_DONE)
144
->save();
145
} catch (Exception $ex) {
146
$command
147
->setStatus(NuanceItemCommand::STATUS_FAILED)
148
->save();
149
150
throw $ex;
151
}
152
}
153
}
154
155
private function newLock($item_phid) {
156
$hash = PhabricatorHash::digestForIndex($item_phid);
157
$lock_key = "nuance.item.{$hash}";
158
return PhabricatorGlobalLock::newLock($lock_key);
159
}
160
161
}
162
163