mirror of
https://github.com/uqbar-dao/nectar.git
synced 2024-11-22 03:04:35 +03:00
add script to build windows artifact; fix bugs
This commit is contained in:
parent
4727de6f03
commit
1b43493c0e
@ -6,9 +6,15 @@ use lib::types::core::{
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
#[cfg(unix)]
|
||||
const DEFAULT_MAX_OPEN_FDS: u64 = 180;
|
||||
const DEFAULT_FDS_AS_FRACTION_OF_ULIMIT_PERCENTAGE: u64 = 90;
|
||||
#[cfg(target_os = "windows")]
|
||||
const DEFAULT_MAX_OPEN_FDS: u64 = 7_000;
|
||||
|
||||
#[cfg(unix)]
|
||||
const SYS_RESERVED_FDS: u64 = 30;
|
||||
|
||||
const DEFAULT_FDS_AS_FRACTION_OF_ULIMIT_PERCENTAGE: u64 = 90;
|
||||
const DEFAULT_UPDATE_ULIMIT_SECS: u64 = 3600;
|
||||
const _DEFAULT_CULL_FRACTION_DENOMINATOR: u64 = 2;
|
||||
|
||||
@ -46,6 +52,7 @@ impl State {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn update_max_fds_from_ulimit(&mut self, ulimit_max_fds: u64) {
|
||||
let Mode::DynamicMax {
|
||||
ref max_fds_as_fraction_of_ulimit_percentage,
|
||||
@ -104,7 +111,18 @@ pub async fn fd_manager(
|
||||
mut recv_from_loop: MessageReceiver,
|
||||
static_max_fds: Option<u64>,
|
||||
) -> anyhow::Result<()> {
|
||||
// Windows does not allow querying of max fds allowed.
|
||||
// However, it allows some 16m, will expectation of actual
|
||||
// max number open nearer to 10k; set to 7k which should be plenty.
|
||||
// https://techcommunity.microsoft.com/t5/windows-blog-archive/pushing-the-limits-of-windows-handles/ba-p/723848
|
||||
#[cfg(target_os = "windows")]
|
||||
let static_max_fds = match static_max_fds {
|
||||
Some(smf) => Some(smf),
|
||||
None => Some(DEFAULT_MAX_OPEN_FDS),
|
||||
};
|
||||
|
||||
let mut state = State::new(static_max_fds);
|
||||
#[cfg(unix)]
|
||||
let mut interval = {
|
||||
// in code block to release the reference into state
|
||||
let Mode::DynamicMax {
|
||||
@ -117,12 +135,12 @@ pub async fn fd_manager(
|
||||
tokio::time::interval(tokio::time::Duration::from_secs(*update_ulimit_secs))
|
||||
};
|
||||
loop {
|
||||
#[cfg(unix)]
|
||||
tokio::select! {
|
||||
Some(message) = recv_from_loop.recv() => {
|
||||
match handle_message(
|
||||
&our_node,
|
||||
message,
|
||||
&mut interval,
|
||||
&mut state,
|
||||
&send_to_loop,
|
||||
).await {
|
||||
@ -151,13 +169,31 @@ pub async fn fd_manager(
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(target_os = "windows")]
|
||||
if let Some(message) = recv_from_loop.recv().await {
|
||||
match handle_message(
|
||||
&our_node,
|
||||
message,
|
||||
&mut state,
|
||||
&send_to_loop,
|
||||
).await {
|
||||
Ok(Some(to_print)) => {
|
||||
Printout::new(2, to_print).send(&send_to_terminal).await;
|
||||
}
|
||||
Err(e) => {
|
||||
Printout::new(1, &format!("handle_message error: {e:?}"))
|
||||
.send(&send_to_terminal)
|
||||
.await;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_message(
|
||||
our_node: &str,
|
||||
km: KernelMessage,
|
||||
_interval: &mut tokio::time::Interval,
|
||||
state: &mut State,
|
||||
send_to_loop: &MessageSender,
|
||||
) -> anyhow::Result<Option<String>> {
|
||||
@ -282,6 +318,7 @@ async fn handle_message(
|
||||
Ok(return_value)
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
async fn update_max_fds(state: &mut State) -> anyhow::Result<u64> {
|
||||
let ulimit_max_fds = get_max_fd_limit()
|
||||
.map_err(|_| anyhow::anyhow!("Couldn't update max fd limit: ulimit failed"))?;
|
||||
@ -289,6 +326,21 @@ async fn update_max_fds(state: &mut State) -> anyhow::Result<u64> {
|
||||
Ok(ulimit_max_fds)
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn get_max_fd_limit() -> anyhow::Result<u64> {
|
||||
let mut rlim = libc::rlimit {
|
||||
rlim_cur: 0, // Current limit
|
||||
rlim_max: 0, // Maximum limit value
|
||||
};
|
||||
|
||||
// RLIMIT_NOFILE is the resource indicating the maximum file descriptor number.
|
||||
if unsafe { libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) } == 0 {
|
||||
Ok(rlim.rlim_cur as u64)
|
||||
} else {
|
||||
Err(anyhow::anyhow!("Failed to get the resource limit."))
|
||||
}
|
||||
}
|
||||
|
||||
async fn send_all_fds_limits(our_node: &str, send_to_loop: &MessageSender, state: &State) {
|
||||
for (process_id, limit) in &state.fds_limits {
|
||||
KernelMessage::builder()
|
||||
@ -309,20 +361,6 @@ async fn send_all_fds_limits(our_node: &str, send_to_loop: &MessageSender, state
|
||||
}
|
||||
}
|
||||
|
||||
fn get_max_fd_limit() -> anyhow::Result<u64> {
|
||||
let mut rlim = libc::rlimit {
|
||||
rlim_cur: 0, // Current limit
|
||||
rlim_max: 0, // Maximum limit value
|
||||
};
|
||||
|
||||
// RLIMIT_NOFILE is the resource indicating the maximum file descriptor number.
|
||||
if unsafe { libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) } == 0 {
|
||||
Ok(rlim.rlim_cur as u64)
|
||||
} else {
|
||||
Err(anyhow::anyhow!("Failed to get the resource limit."))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn send_fd_manager_request_fds_limit(our: &Address, send_to_loop: &MessageSender) {
|
||||
let message = Message::Request(Request {
|
||||
inherit: false,
|
||||
|
@ -1 +1,3 @@
|
||||
npm install && npm run build:copy
|
||||
#!/bin/bash
|
||||
|
||||
npm install && npm run build:copy
|
||||
|
97
scripts/build-windows-artifact.py
Executable file
97
scripts/build-windows-artifact.py
Executable file
@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import zipfile
|
||||
|
||||
def is_excluded(path, excludes, include_files):
|
||||
path = os.path.abspath(path)
|
||||
# If the path is in include_files, do not exclude it
|
||||
if path in include_files:
|
||||
return False
|
||||
for exclude in excludes:
|
||||
if os.path.commonpath([path, exclude]) == exclude:
|
||||
return True
|
||||
return False
|
||||
|
||||
def parse_args(repo_root):
|
||||
parser = argparse.ArgumentParser(description='Build Windows artifact.')
|
||||
parser.add_argument(
|
||||
'--exclude',
|
||||
action='append',
|
||||
default=[],
|
||||
help='Exclude directories (relative to repo root). Can be used multiple times.'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--output',
|
||||
default=os.path.join(repo_root, 'target', 'windows-artifact.zip'),
|
||||
help='Output zip file path.'
|
||||
)
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
def main():
|
||||
# Get the directory where the script is located
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
# Assume the repo root is one level up from the script directory
|
||||
repo_root = os.path.abspath(os.path.join(script_dir, '..'))
|
||||
|
||||
args = parse_args(repo_root)
|
||||
|
||||
default_excludes = [
|
||||
'.git',
|
||||
'kinode/packages',
|
||||
'target',
|
||||
'kinode/src/register-ui/node_modules',
|
||||
]
|
||||
excludes = default_excludes + args.exclude
|
||||
|
||||
# Convert exclude paths to absolute paths
|
||||
excludes = [os.path.abspath(os.path.join(repo_root, p)) for p in excludes]
|
||||
|
||||
# Include 'target/packages.zip' even though 'target' is excluded
|
||||
include_files = [
|
||||
os.path.abspath(os.path.join(repo_root, 'target', 'packages.zip'))
|
||||
]
|
||||
|
||||
# Run the build scripts
|
||||
build_script_dir = os.path.join(repo_root, 'kinode', 'src', 'register-ui')
|
||||
build_script_name = 'build.sh'
|
||||
build_script = os.path.join(build_script_dir, build_script_name)
|
||||
if not os.path.exists(build_script):
|
||||
print(f'Build script not found at {build_script}')
|
||||
sys.exit(1)
|
||||
|
||||
# Execute the build script
|
||||
subprocess.check_call([f'./{build_script_name}'], cwd=build_script_dir)
|
||||
|
||||
# Run cargo build
|
||||
subprocess.check_call(['cargo', 'build', '-p', 'build_packages'], cwd=repo_root)
|
||||
|
||||
# Create the zip file
|
||||
output_zip = args.output
|
||||
output_zip_abs = os.path.abspath(output_zip)
|
||||
output_dir = os.path.dirname(output_zip_abs)
|
||||
if output_dir and not os.path.exists(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
|
||||
# Exclude the output zip file itself
|
||||
excludes.append(output_zip_abs)
|
||||
|
||||
with zipfile.ZipFile(output_zip_abs, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
||||
for root, dirs, files in os.walk(repo_root):
|
||||
for file in files:
|
||||
file_path = os.path.join(root, file)
|
||||
if is_excluded(file_path, excludes, include_files):
|
||||
continue
|
||||
rel_path = os.path.relpath(file_path, repo_root)
|
||||
if ':' in str(rel_path):
|
||||
# Replace ':' in filenames to make them valid on Windows
|
||||
rel_path = rel_path.replace(':', '_')
|
||||
print(f'Unexpected `:` in filename: {rel_path}; replacing with `_` in zip file')
|
||||
zipf.write(file_path, rel_path)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue
Block a user