-
-
Notifications
You must be signed in to change notification settings - Fork 360
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Acquire a lock on the out dir in order to run tasks / commands (#3599)
First cut at #3519 There's no tests yet, but it works fine in manual tests.
- Loading branch information
1 parent
8b063c4
commit fe73de8
Showing
9 changed files
with
198 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 92 additions & 0 deletions
92
integration/feature/output-directory/src/OutputDirectoryLockTests.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package mill.integration | ||
|
||
import mill.testkit.UtestIntegrationTestSuite | ||
import utest._ | ||
|
||
import java.io.ByteArrayOutputStream | ||
import java.util.concurrent.{CountDownLatch, Executors} | ||
|
||
import scala.concurrent.duration.Duration | ||
import scala.concurrent.{Await, ExecutionContext, Future} | ||
|
||
object OutputDirectoryLockTests extends UtestIntegrationTestSuite { | ||
|
||
private val pool = Executors.newCachedThreadPool() | ||
private val ec = ExecutionContext.fromExecutorService(pool) | ||
|
||
override def utestAfterAll(): Unit = { | ||
pool.shutdown() | ||
} | ||
|
||
def tests: Tests = Tests { | ||
test("basic") - integrationTest { tester => | ||
import tester._ | ||
val signalFile = workspacePath / "do-wait" | ||
System.err.println("Spawning blocking task") | ||
val blocksFuture = | ||
Future(eval(("show", "blockWhileExists", "--path", signalFile), check = true))(ec) | ||
while (!os.exists(signalFile) && !blocksFuture.isCompleted) | ||
Thread.sleep(100L) | ||
if (os.exists(signalFile)) | ||
System.err.println("Blocking task is running") | ||
else { | ||
System.err.println("Failed to run blocking task") | ||
Predef.assert(blocksFuture.isCompleted) | ||
blocksFuture.value.get.get | ||
} | ||
|
||
val testCommand: os.Shellable = ("show", "hello") | ||
val testMessage = "Hello from hello task" | ||
|
||
System.err.println("Evaluating task without lock") | ||
val noLockRes = eval(("--no-build-lock", testCommand), check = true) | ||
assert(noLockRes.out.contains(testMessage)) | ||
|
||
System.err.println("Evaluating task without waiting for lock (should fail)") | ||
val noWaitRes = eval(("--no-wait-for-build-lock", testCommand)) | ||
assert(noWaitRes.err.contains("Cannot proceed, another Mill process is running tasks")) | ||
|
||
System.err.println("Evaluating task waiting for the lock") | ||
|
||
val lock = new CountDownLatch(1) | ||
val stderr = new ByteArrayOutputStream | ||
var success = false | ||
val futureWaitingRes = Future { | ||
eval( | ||
testCommand, | ||
stderr = os.ProcessOutput { | ||
val expectedMessage = | ||
"Another Mill process is running tasks, waiting for it to be done..." | ||
|
||
(bytes, len) => | ||
stderr.write(bytes, 0, len) | ||
val output = new String(stderr.toByteArray) | ||
if (output.contains(expectedMessage)) | ||
lock.countDown() | ||
}, | ||
check = true | ||
) | ||
}(ec) | ||
try { | ||
lock.await() | ||
success = true | ||
} finally { | ||
if (!success) { | ||
System.err.println("Waiting task output:") | ||
System.err.write(stderr.toByteArray) | ||
} | ||
} | ||
|
||
System.err.println("Task is waiting for the lock, unblocking it") | ||
os.remove(signalFile) | ||
|
||
System.err.println("Blocking task should exit") | ||
val blockingRes = Await.result(blocksFuture, Duration.Inf) | ||
assert(blockingRes.out.contains("Blocking command done")) | ||
|
||
System.err.println("Waiting task should be free to proceed") | ||
val waitingRes = Await.result(futureWaitingRes, Duration.Inf) | ||
assert(waitingRes.out.contains(testMessage)) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package mill.main.client.lock; | ||
|
||
import java.util.concurrent.locks.ReentrantLock; | ||
|
||
class DummyLock extends Lock { | ||
|
||
public boolean probe() { | ||
return true; | ||
} | ||
|
||
public Locked lock() { | ||
return new DummyTryLocked(); | ||
} | ||
|
||
public TryLocked tryLock() { | ||
return new DummyTryLocked(); | ||
} | ||
|
||
@Override | ||
public void close() throws Exception { | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package mill.main.client.lock; | ||
|
||
class DummyTryLocked implements TryLocked { | ||
public DummyTryLocked() { | ||
} | ||
|
||
public boolean isLocked(){ return true; } | ||
|
||
public void release() throws Exception { | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters