Skip to content

Commit 5dd64d0

Browse files
committed
Add an extension to support Revise
1 parent efe8e4d commit 5dd64d0

File tree

4 files changed

+103
-1
lines changed

4 files changed

+103
-1
lines changed

Project.toml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,16 @@ Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
77
Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
88
Sockets = "6462fe0b-24de-5631-8697-dd941f90decc"
99

10+
[weakdeps]
11+
Revise = "295af30f-e4ad-537b-8983-00126c2a3abe"
12+
13+
[extensions]
14+
ReviseExt = "Revise"
15+
1016
[compat]
1117
Distributed = "1"
1218
Random = "1"
19+
Revise = "3.7.0"
1320
Serialization = "1"
1421
Sockets = "1"
1522
julia = "1.9"
@@ -21,4 +28,4 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
2128
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
2229

2330
[targets]
24-
test = ["LinearAlgebra", "Test", "LibSSH", "Distributed"]
31+
test = ["LinearAlgebra", "Test", "LibSSH", "Distributed", "Revise"]

docs/src/_changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ This documents notable changes in DistributedNext.jl. The format is based on
1919
- [`other_workers()`](@ref) and [`other_procs()`](@ref) were implemented and
2020
exported ([#18]).
2121
- Implemented callback support for workers being added/removed etc ([#17]).
22+
- Added a package extension to support Revise.jl ([#17]).
2223

2324
## [v1.0.0] - 2024-12-02
2425

ext/ReviseExt.jl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
module ReviseExt
2+
3+
import DistributedNext
4+
import DistributedNext: myid, workers, remotecall
5+
6+
import Revise
7+
8+
9+
struct DistributedNextWorker <: Revise.AbstractWorker
10+
id::Int
11+
end
12+
13+
function get_workers()
14+
map(DistributedNextWorker, workers())
15+
end
16+
17+
function Revise.remotecall_impl(f, worker::DistributedNextWorker, args...; kwargs...)
18+
remotecall(f, worker.id, args...; kwargs...)
19+
end
20+
21+
Revise.is_master_worker(::typeof(get_workers)) = myid() == 1
22+
Revise.is_master_worker(worker::DistributedNextWorker) = worker.id == 1
23+
24+
function __init__()
25+
Revise.register_workers_function(get_workers)
26+
DistributedNext.add_worker_started_callback(pid -> Revise.init_worker(DistributedNextWorker(pid));
27+
key="DistributedNext-integration")
28+
end
29+
30+
end

test/distributed_exec.jl

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# This file is a part of Julia. License is MIT: https://julialang.org/license
22

3+
import Revise
34
using DistributedNext, Random, Serialization, Sockets
45
import DistributedNext
56
import DistributedNext: launch, manage
@@ -1993,6 +1994,69 @@ end
19931994
@test length(exited_workers) == 1
19941995
end
19951996

1997+
# This is a simplified copy of a test from Revise.jl's tests
1998+
@testset "Revise.jl integration" begin
1999+
function rm_precompile(pkgname::AbstractString)
2000+
filepath = Base.cache_file_entry(Base.PkgId(pkgname))
2001+
isa(filepath, Tuple) && (filepath = filepath[1]*filepath[2]) # Julia 1.3+
2002+
for depot in DEPOT_PATH
2003+
fullpath = joinpath(depot, filepath)
2004+
isfile(fullpath) && rm(fullpath)
2005+
end
2006+
end
2007+
2008+
pid = only(addprocs(1))
2009+
2010+
# Test that initialization succeeds by checking that Main.whichtt is defined
2011+
# on the worker, which is defined by Revise.init_worker().
2012+
@test timedwait(() ->remotecall_fetch(() -> hasproperty(Main, :whichtt), pid), 10) == :ok
2013+
2014+
tmpdir = mktempdir()
2015+
@everywhere push!(LOAD_PATH, $tmpdir) # Don't want to share this LOAD_PATH
2016+
2017+
# Create a fake package
2018+
module_file = joinpath(tmpdir, "ReviseDistributed", "src", "ReviseDistributed.jl")
2019+
mkpath(dirname(module_file))
2020+
write(module_file,
2021+
"""
2022+
module ReviseDistributed
2023+
2024+
f() = π
2025+
g(::Int) = 0
2026+
2027+
end
2028+
""")
2029+
2030+
# Check that we can use it
2031+
@everywhere using ReviseDistributed
2032+
for p in procs()
2033+
@test remotecall_fetch(ReviseDistributed.f, p) == π
2034+
@test remotecall_fetch(ReviseDistributed.g, p, 1) == 0
2035+
end
2036+
2037+
# Test changing and deleting methods
2038+
write(module_file,
2039+
"""
2040+
module ReviseDistributed
2041+
2042+
f() = 3.0
2043+
2044+
end
2045+
""")
2046+
Revise.revise()
2047+
for p in procs()
2048+
# We use timedwait() here because worker updates from Revise are asynchronous
2049+
@test timedwait(() -> remotecall_fetch(ReviseDistributed.f, p) == 3.0, 10) == :ok
2050+
2051+
@test_throws RemoteException remotecall_fetch(ReviseDistributed.g, p, 1)
2052+
end
2053+
2054+
rmprocs(workers())
2055+
rm_precompile("ReviseDistributed")
2056+
pop!(LOAD_PATH)
2057+
end
2058+
2059+
19962060
# Run topology tests last after removing all workers, since a given
19972061
# cluster at any time only supports a single topology.
19982062
if nprocs() > 1

0 commit comments

Comments
 (0)