@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3abstract class DiffusionFileFutureQuery
4 extends DiffusionQuery {
5
6 private $timeout;
7 private $byteLimit;
8
9 private $didHitByteLimit = false;
10 private $didHitTimeLimit = false;
11
12 public static function getConduitParameters() {
13 return array(
14 'timeout' => 'optional int',
15 'byteLimit' => 'optional int',
16 );
17 }
18
19 public function setTimeout($timeout) {
20 $this->timeout = $timeout;
21 return $this;
22 }
23
24 public function getTimeout() {
25 return $this->timeout;
26 }
27
28 public function setByteLimit($byte_limit) {
29 $this->byteLimit = $byte_limit;
30 return $this;
31 }
32
33 public function getByteLimit() {
34 return $this->byteLimit;
35 }
36
37 final public function getExceededByteLimit() {
38 return $this->didHitByteLimit;
39 }
40
41 final public function getExceededTimeLimit() {
42 return $this->didHitTimeLimit;
43 }
44
45 abstract protected function newQueryFuture();
46
47 final public function respondToConduitRequest(ConduitAPIRequest $request) {
48 $drequest = $this->getRequest();
49
50 $timeout = $request->getValue('timeout');
51 if ($timeout) {
52 $this->setTimeout($timeout);
53 }
54
55 $byte_limit = $request->getValue('byteLimit');
56 if ($byte_limit) {
57 $this->setByteLimit($byte_limit);
58 }
59
60 $file = $this->execute();
61
62 $too_slow = (bool)$this->getExceededTimeLimit();
63 $too_huge = (bool)$this->getExceededByteLimit();
64
65 $file_phid = null;
66 if (!$too_slow && !$too_huge) {
67 $repository = $drequest->getRepository();
68 $repository_phid = $repository->getPHID();
69
70 $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
71 $file->attachToObject($repository_phid);
72 unset($unguarded);
73
74 $file_phid = $file->getPHID();
75 }
76
77 return array(
78 'tooSlow' => $too_slow,
79 'tooHuge' => $too_huge,
80 'filePHID' => $file_phid,
81 );
82 }
83
84 final public function executeInline() {
85 $future = $this->newConfiguredQueryFuture();
86 list($stdout) = $future->resolvex();
87 return $stdout;
88 }
89
90 final protected function executeQuery() {
91 $future = $this->newConfiguredQueryFuture();
92
93 $drequest = $this->getRequest();
94
95 $name = basename($drequest->getPath());
96 $relative_ttl = phutil_units('48 hours in seconds');
97
98 try {
99 $threshold = PhabricatorFileStorageEngine::getChunkThreshold();
100 $future->setReadBufferSize($threshold);
101
102 $source = id(new PhabricatorExecFutureFileUploadSource())
103 ->setName($name)
104 ->setRelativeTTL($relative_ttl)
105 ->setViewPolicy(PhabricatorPolicies::POLICY_NOONE)
106 ->setExecFuture($future);
107
108 $byte_limit = $this->getByteLimit();
109 if ($byte_limit) {
110 $source->setByteLimit($byte_limit);
111 }
112
113 $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
114 $file = $source->uploadFile();
115 unset($unguarded);
116
117 } catch (CommandException $ex) {
118 if (!$future->getWasKilledByTimeout()) {
119 throw $ex;
120 }
121
122 $this->didHitTimeLimit = true;
123 $file = null;
124 } catch (PhabricatorFileUploadSourceByteLimitException $ex) {
125 $this->didHitByteLimit = true;
126 $file = null;
127 }
128
129 return $file;
130 }
131
132 private function newConfiguredQueryFuture() {
133 $future = $this->newQueryFuture();
134
135 if ($this->getTimeout()) {
136 $future->setTimeout($this->getTimeout());
137 }
138
139 return $future;
140 }
141
142}