Skip to content
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

Introduce NativeLink Web Bridge #1289

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@
};
};

nativelink-bridge = pkgs.callPackage ./web/bridge/image.nix {inherit buildImage pullImage pkgs;};

nativelink-worker-init = pkgs.callPackage ./tools/nativelink-worker-init.nix {inherit buildImage self nativelink-image;};

rbe-autogen = pkgs.callPackage ./local-remote-execution/rbe-autogen.nix {
Expand Down Expand Up @@ -419,6 +421,7 @@
nativelink-worker-init
nativelink-x86_64-linux
publish-ghcr
nativelink-bridge
;
default = nativelink;

Expand Down
177 changes: 177 additions & 0 deletions nativelink-config/examples/basic_bes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
{
"stores": {
"AC_MAIN_STORE": {
"filesystem": {
"content_path": "/tmp/nativelink/data-worker-test/content_path-ac",
"temp_path": "/tmp/nativelink/data-worker-test/tmp_path-ac",
"eviction_policy": {
"max_bytes": 100000000000
}
}
},
"BEP_STORE": {
"redis_store": {
"addresses": [
"redis://@localhost:6379/0"
],
"response_timeout_s": 5,
"connection_timeout_s": 5,
"experimental_pub_sub_channel": "build_event",
"key_prefix": "nativelink:",
"mode": "standard"
}
},
"WORKER_FAST_SLOW_STORE": {
"fast_slow": {
"fast": {
"filesystem": {
"content_path": "/tmp/nativelink/data-worker-test/content_path-cas",
"temp_path": "/tmp/nativelink/data-worker-test/tmp_path-cas",
"eviction_policy": {
"max_bytes": 100000000000
}
}
},
"slow": {
"noop": {}
}
}
}
},
"schedulers": {
"MAIN_SCHEDULER": {
"simple": {
"supported_platform_properties": {
"cpu_count": "minimum",
"memory_kb": "minimum",
"network_kbps": "minimum",
"disk_read_iops": "minimum",
"disk_read_bps": "minimum",
"disk_write_iops": "minimum",
"disk_write_bps": "minimum",
"shm_size": "minimum",
"gpu_count": "minimum",
"gpu_model": "exact",
"cpu_vendor": "exact",
"cpu_arch": "exact",
"cpu_model": "exact",
"kernel_version": "exact",
"OSFamily": "priority",
"container-image": "priority"
}
}
}
},
"workers": [
{
"local": {
"worker_api_endpoint": {
"uri": "grpc://127.0.0.1:50062"
},
"cas_fast_slow_store": "WORKER_FAST_SLOW_STORE",
"upload_action_result": {
"ac_store": "AC_MAIN_STORE"
},
"work_directory": "/tmp/nativelink/work",
"platform_properties": {
"cpu_count": {
"values": [
"16"
]
},
"memory_kb": {
"values": [
"500000"
]
},
"network_kbps": {
"values": [
"100000"
]
},
"cpu_arch": {
"values": [
"x86_64"
]
},
"OSFamily": {
"values": [
""
]
},
"container-image": {
"values": [
""
]
}
}
}
}
],
"servers": [
{
"name": "public",
"listener": {
"http": {
"socket_address": "0.0.0.0:50052"
}
},
"services": {
"cas": {
"main": {
"cas_store": "WORKER_FAST_SLOW_STORE"
}
},
"ac": {
"main": {
"ac_store": "AC_MAIN_STORE"
}
},
"execution": {
"main": {
"cas_store": "WORKER_FAST_SLOW_STORE",
"scheduler": "MAIN_SCHEDULER"
}
},
"capabilities": {
"main": {
"remote_execution": {
"scheduler": "MAIN_SCHEDULER"
}
}
},
"bytestream": {
"cas_stores": {
"main": "WORKER_FAST_SLOW_STORE"
}
}
}
},
{
"name": "private_workers_servers",
"listener": {
"http": {
"socket_address": "0.0.0.0:50062"
}
},
"services": {
"experimental_prometheus": {
"path": "/metrics"
},
"experimental_bep": {
"store": "BEP_STORE"
},
"worker_api": {
"scheduler": "MAIN_SCHEDULER"
},
"admin": {},
"health": {
"path": "/status"
}
}
}
],
"global": {
"max_open_files": 512
}
}
1 change: 1 addition & 0 deletions tools/pre-commit-hooks.nix
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ in {

# Bun binary lockfile
"web/platform/bun.lockb"
"web/bridge/bun.lockb"
];
enable = true;
types = ["binary"];
Expand Down
5 changes: 5 additions & 0 deletions web/bridge/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
REDIS_URL=redis://localhost:6379
NATIVELINK_PUB_SUB_CHANNEL=build_event
POSTGRES_URL=postgres://username:password@host:port/database
WEBSOCKET_PORT=8080
HTTP_PORT=3001
30 changes: 30 additions & 0 deletions web/bridge/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Logs
logs

# Caches
.cache

# Runtime data
pids
_.pid
_.seed
*.pid.lock

# Dependency directories
node_modules/

# TypeScript cache
*.tsbuildinfo

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# distribution directory
dist

# temporary files
.temp
79 changes: 79 additions & 0 deletions web/bridge/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# NativeLink Bridge (Experimental)

Make sure you are running an instance of Redis or DragonflyDB in your network.

For DragonflyDB inside docker run:

```bash
docker run \
-d --name some-dragonfly \
-p 6379:6379 \
--ulimit memlock=-1 \
docker.dragonflydb.io/dragonflydb/dragonfly

```

For Redis inside docker run:

```bash
docker run -d --name some-redis \
-p 6379:6379 \
redis
```

Set the Redis URL and the NativeLink pub sub channel ENV variables in `.env` as defined in the `.env.example`


The Redis URL format: 'redis://alice:[email protected]:6380'

The NativeLink pub sub channel ENV variable should match `experimental_pub_sub_channel` inside `nativelink-config/example/basic_bes.json`.

Make sure you have set also the `key_prefix` in `nativelink-config/example/basic_bes.json`

## You need 4 Components + Redis

### 1. NativeLink

Start an instance of NativeLink with the basic_bes.json inside the `nativelink-config/example/basic_bes.json`.

### 2. NativeLink Web Bridge

Install the dependencies and run the bridge:

```bash
bun i && bun run index.ts
```

### 3. NativeLink Web UI

Inside the web/ui directory run:

```bash
bun i & bun dev
```

Now you can open http://localhost:4321.


### 4. Bazel

Now you can run your Bazel build with NativeLink and see it in real-time going into the web app

Include this in your .bazelrc
```bash
bazel clean && bazel build \
--remote_cache=grpc://localhost:50051 \
--remote_executor=grpc://localhost:50051 \
--bes_backend=grpc://localhost:50061 \
--bes_results_url=http://localhost:4321/builds \
--bes_upload_mode=fully_async \
--build_event_publish_all_actions=true \
//local-remote-execution/examples:hello_lre
```

Make sure to use the right IP, if it's not hosted on `localhost`


```bash
bazel build some-target
```
Binary file added web/bridge/bun.lockb
Binary file not shown.
32 changes: 32 additions & 0 deletions web/bridge/image.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
pkgs,
buildImage,
...
}: let
# NativeLink Bridge
nativelink-bridge = pkgs.stdenv.mkDerivation {
name = "nativelink-bridge";
src = ./.;
buildInputs = [pkgs.bun];
installPhase = ''
mkdir -p $out
cp -r $src/* $out
'';
};
in
buildImage {
name = "nativelink-bridge";

# Container configuration
config = {
WorkingDir = "${nativelink-bridge}";
Entrypoint = ["${pkgs.bun}/bin/bun" "run" "index.ts"];
ExposedPorts = {
"8080/tcp" = {};
};
Labels = {
"org.opencontainers.image.description" = "A simple Bun environment image";
"org.opencontainers.image.title" = "Bun Environment";
};
};
}
3 changes: 3 additions & 0 deletions web/bridge/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { start } from './src';

start().catch(err => console.error(err));
22 changes: 22 additions & 0 deletions web/bridge/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "nativelink-bridge",
"version": "0.5.3",
"module": "index.ts",
"type": "module",
"dependencies": {
"drizzle-orm": "^0.36.0",
"postgres": "^3.4.5",
"protobufjs": "^7.4.0",
"redis": "^4.7.0"
},
"devDependencies": {
"@types/bun": "^1.1.8",
"drizzle-kit": "^0.27.1"
},
"peerDependencies": {
"typescript": "^5.0.0"
},
"trustedDependencies": [
"protobufjs"
]
}
9 changes: 9 additions & 0 deletions web/bridge/src/db/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { drizzle } from "drizzle-orm/postgres-js";

const postgresConfig = process.env.POSTGRES_URL || "postgres://user:password@localhost:5432/postgres"

const db = drizzle(postgresConfig);

export const build_data = await db.execute('select * from build_data');

export { db };
Loading