Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 46
Hot reload#25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Hot reload #25
Changes from all commits
d7c764cda34cedc763d0b24b44a9c5b68fc74fd13e04f56d4971d89ee856af7fdf9e12dddb875556f8388432617e3f419414e8168262cbba1aac87bf297b27e71add4e169159921e3e4f8ce6c64b8636d27a2607ff2adccFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| module Dash | ||
| import HTTP, JSON2, CodecZlib, MD5 | ||
| using Sockets | ||
| using MacroTools | ||
| const ROOT_PATH = realpath(joinpath(@__DIR__, "..")) | ||
| include("Components.jl") | ||
| @@ -19,7 +20,6 @@ include("utils.jl") | ||
| include("app.jl") | ||
| include("resources/registry.jl") | ||
| include("resources/application.jl") | ||
| include("config.jl") | ||
| include("handlers.jl") | ||
| @doc """ | ||
| @@ -31,7 +31,7 @@ Julia backend for [Plotly Dash](https://github.com/plotly/dash) | ||
| ```julia | ||
| using Dash | ||
| app = dash("Test", external_stylesheets=["https://codepen.io/chriddyp/pen/bWLwgP.css"]) do | ||
| app = dash(external_stylesheets=["https://codepen.io/chriddyp/pen/bWLwgP.css"]) do | ||
| html_div() do | ||
| dcc_input(id="graphTitle", value="Let's Dance!", type = "text"), | ||
| html_div(id="outputID"), | ||
| @@ -76,7 +76,7 @@ Run Dash server | ||
| #Examples | ||
| ```jldoctest | ||
| julia> app = dash("Test") do | ||
| julia> app = dash() do | ||
| html_div() do | ||
| html_h1("Test Dashboard") | ||
| end | ||
| @@ -111,10 +111,53 @@ function run_server(app::DashApp, host = HTTP.Sockets.localhost, port = 8050; | ||
| dev_tools_silence_routes_logging = dev_tools_silence_routes_logging, | ||
| dev_tools_prune_errors = dev_tools_prune_errors | ||
| ) | ||
| handler = make_handler(app); | ||
| @info string("Running on http://", host, ":", port) | ||
| HTTP.serve(handler, host, port) | ||
| end | ||
| main_func = () -> begin | ||
| ccall(:jl_exit_on_sigint, Cvoid, (Cint,), 0) | ||
rpkyle marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| handler = make_handler(app); | ||
| try | ||
| task = @async HTTP.serve(handler, host, port) | ||
rpkyle marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| @info string("Running on http://", host, ":", port) | ||
| wait(task) | ||
| catch e | ||
| if e isa InterruptException | ||
| @info "exited" | ||
| else | ||
| rethrow(e) | ||
| end | ||
| end | ||
| end | ||
| start_server = () -> begin | ||
| handler = make_handler(app); | ||
| server = Sockets.listen(get_inetaddr(host, port)) | ||
| task = @async HTTP.serve(handler, host, port; server = server) | ||
| @info string("Running on http://", host, ":", port) | ||
| return (server, task) | ||
| end | ||
| if get_devsetting(app, :hot_reload) && !is_hot_restart_available() | ||
| @warn "Hot reloading is disabled for interactive sessions. Please run your app using julia from the command line to take advantage of this feature." | ||
| end | ||
| if get_devsetting(app, :hot_reload) && is_hot_restart_available() | ||
| hot_restart(start_server, check_interval = get_devsetting(app, :hot_reload_watch_interval)) | ||
| else | ||
| (server, task) = start_server() | ||
| try | ||
| wait(task) | ||
| println(task) | ||
| catch e | ||
| close(server) | ||
| if e isa InterruptException | ||
| println("finished") | ||
| return | ||
| else | ||
| rethrow(e) | ||
| end | ||
| end | ||
| end | ||
| end | ||
| get_inetaddr(host::String, port::Integer) = Sockets.InetAddr(parse(IPAddr, host), port) | ||
| get_inetaddr(host::IPAddr, port::Integer) = Sockets.InetAddr(host, port) | ||
| end # module | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -18,6 +18,7 @@ function process_dependencies(request::HTTP.Request, state::HandlerState) | ||
| end | ||
| function process_index(request::HTTP.Request, state::HandlerState) | ||
| get_cache(state).need_recache && rebuild_cache!(state) | ||
| return HTTP.Response( | ||
| 200, | ||
| ["Content-Type" => "text/html"], | ||
| @@ -147,7 +148,7 @@ end | ||
| function process_assets(request::HTTP.Request, state::HandlerState; file_path::AbstractString) | ||
| app = state.app | ||
| filename = joinpath(get_setting(app, :assets_folder), file_path) | ||
| filename = joinpath(get_assets_path(app), file_path) | ||
| try | ||
| headers = Pair{String,String}[] | ||
| @@ -161,7 +162,47 @@ function process_assets(request::HTTP.Request, state::HandlerState; file_path::A | ||
| end | ||
| const dash_router = HTTP.Router() | ||
| function process_reload_hash(request::HTTP.Request, state::HandlerState) | ||
| reload_tuple = ( | ||
| reloadHash = state.reload.hash, | ||
| hard = state.reload.hard, | ||
| packages = keys(state.cache.resources.files), | ||
| files = state.reload.changed_assets | ||
| ) | ||
| state.reload.hard = false | ||
| state.reload.changed_assets = [] | ||
| return HTTP.Response(200, ["Content-Type" => "application/json"], body = JSON2.write(reload_tuple)) | ||
| end | ||
| function start_reload_poll(state::HandlerState) | ||
| folders = Set{String}() | ||
| push!(folders, get_assets_path(state.app)) | ||
| push!(folders, state.registry.dash_renderer.path) | ||
| for pkg in values(state.registry.components) | ||
| push!(folders, pkg.path) | ||
| end | ||
| state.reload.task = @async poll_folders(folders; interval = get_devsetting(state.app, :hot_reload_watch_interval)) do file, ts, deleted | ||
rpkyle marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| state.reload.hard = true | ||
| state.reload.hash = generate_hash() | ||
| assets_path = get_assets_path(state.app) | ||
| if startswith(file, assets_path) | ||
| state.cache.need_recache = true | ||
| rel_path = lstrip( | ||
| replace(relpath(file, assets_path), '\\'=>'/'), | ||
| '/' | ||
| ) | ||
| push!(state.reload.changed_assets, | ||
| ChangedAsset( | ||
| asset_path(state.app, rel_path), | ||
| trunc(Int, ts), | ||
| endswith(file, "css") | ||
| ) | ||
| ) | ||
| end | ||
| end | ||
| end | ||
| validate_layout(layout::Component) = validate(layout) | ||
| @@ -180,6 +221,7 @@ function make_handler(app::DashApp, registry::ResourcesRegistry; check_layout = | ||
| router = Router() | ||
| add_route!(process_layout, router, "$(prefix)_dash-layout") | ||
| add_route!(process_dependencies, router, "$(prefix)_dash-dependencies") | ||
| add_route!(process_reload_hash, router, "$(prefix)_reload-hash") | ||
| add_route!(process_resource, router, "$(prefix)_dash-component-suites/<namespace>/<path>") | ||
| add_route!(process_assets, router, "$(prefix)$(assets_url_path)/<file_path>") | ||
| add_route!(process_callback, router, "POST", "$(prefix)_dash-update-component") | ||
| @@ -189,7 +231,12 @@ function make_handler(app::DashApp, registry::ResourcesRegistry; check_layout = | ||
| handler = state_handler(router, state) | ||
| get_setting(app, :compress) && (handler = compress_handler(handler)) | ||
| HTTP.handle(handler, HTTP.Request("GET", prefix)) #For handler precompilation | ||
| compile_request = HTTP.Request("GET", prefix) | ||
| HTTP.setheader(compile_request, "Accept-Encoding" => "gzip") | ||
| HTTP.handle(handler, compile_request) #For handler precompilation | ||
| get_devsetting(app, :hot_reload) && start_reload_poll(state) | ||
| return handler | ||
| end | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.