Functions
View MarkdownA Function is a Python function that runs on Nodus workers. You decorate it, call it from your own code with
.remote(), .map() or .spawn(), and Nodus starts workers when calls arrive, keeps them warm for a while and
scales them back down. The pages of this guide cover calling Functions, scaling
them and what is billed while a worker waits.
Run an App
Section titled “Run an App”An App is the group of Functions in one file. nodus run creates an ephemeral App, runs your main on your
machine and deletes the App when main returns. Every .remote() call runs on a Nodus worker.
"""One Function called three ways, then mapped over a thousand inputs.
Run it with `nodus run examples/functions/map/app.py`."""
import nodus
app = nodus.App("fn-map")
@app.function(cpu=1, memory="1Gi", max_workers=4, target_concurrency=8, max_cost=1)def square(x: int) -> int: return x * x
@app.function(cpu=1, memory="1Gi", max_cost=1)def divide(a: int, b: int) -> float: return a / b
@app.local_entrypoint()def main(n: int = 1000) -> None: print("remote:", square.remote(7)) # one call; blocks for the result call = square.spawn(8) # starts a call and returns a handle print("spawned:", call.get(timeout=600)) results = list(square.map(range(n))) # one call per input, results in input order print("map:", len(results), "ordered:", results == [i * i for i in range(n)]) try: divide.remote(1, 0) except ZeroDivisionError as exc: # the remote exception comes back as its own type print("raised:", type(exc).__name__)$ nodus run examples/functions/map/app.pyremote: 49spawned: 64map: 1000 ordered: Trueraised: ZeroDivisionErrorThe directory of the file (minus what .gitignore and .nodusignore exclude) is uploaded once per content hash,
so the workers import the same code you ran. The App renews itself while main runs and is deleted shortly after
main stops, even when your machine loses its connection.
Deploy an App
Section titled “Deploy an App”nodus deploy keeps the App. Its Functions stay available after your program exits, and any program can call them.
"""A Function that keeps one worker warm, so a call never waits for a start.
Deploy it with `nodus deploy examples/functions/warm-pool/app.py`. The idle worker is billed at the Function'sworker rate for as long as it stays warm; set `min_workers=0` to pay only while calls run."""
import nodus
app = nodus.App("fn-warm")
@app.function(cpu=1, memory="1Gi", min_workers=1, max_workers=3, scaledown_window="2m", max_cost=1)def ping() -> str: return "pong"$ nodus deploy examples/functions/warm-pool/app.pyimport nodus
ping = nodus.Function.from_name("fn-warm", "ping")print(ping.remote()) # pongA deploy updates the App in place. A Function whose code, image or resources changed rolls its workers once, after
their in-flight calls finish. A Function you removed from the file is deleted, and the calls it still had queued
end as Failed with the reason FunctionDeleted, so no caller waits for a call nobody will run.
What Nodus creates
Section titled “What Nodus creates”| Object | What it is | Look at it with |
|---|---|---|
App |
The Functions of one file; ephemeral for run, persistent for deploy |
nodus get apps |
Function |
One decorated function or class, with its image, resources and scaling |
nodus get functions |
FunctionCall |
One invocation, kept for seven days after it ends | nodus get functioncalls -l nodus.dev/function=fn-warm-ping |
A Function reports its state in status.phase, how many workers it has in status.workers, how many calls wait in
status.queue, and the expected start time in status.estimate.
$ nodus get function fn-warm-pingNAME PHASE WORKERS QUEUED COST AGEfn-warm-ping Running 1/3 0 $0.02 3mStop, restart and delete
Section titled “Stop, restart and delete”$ nodus stop function/fn-warm-ping # drain the workers; new calls wait in the queue$ nodus start function/fn-warm-ping # start workers again for the calls that waited$ nodus restart function/fn-warm-ping # replace every worker once, after in-flight calls finish$ nodus delete app/fn-warmA stopped Function keeps accepting calls and holds them in the queue, so work you submit while it is stopped runs once it starts. Workers also stop by themselves when your balance cannot cover another renewal; calls queue until you add credit and then run.