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

Fix/async await compilation #10

Merged
merged 8 commits into from
Sep 12, 2024
Merged
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file.
1 change: 0 additions & 1 deletion crates/metassr-build/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
pub mod bundler;
pub mod client;
pub mod server;
pub(crate) mod shared;
Expand Down
4 changes: 0 additions & 4 deletions crates/metassr-build/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ use std::{
ffi::OsStr,
fs,
path::{Path, PathBuf},
thread::sleep,
time::Duration,
};
use targets::TargetsGenerator;

Expand Down Expand Up @@ -88,8 +86,6 @@ impl Build for ServerSideBuilder {
return Err(anyhow!("Bundling failed: {e}"));
}

// TODO: find a solution to remove this line
sleep(Duration::from_secs(1));
let dist = DistDir::new(&self.dist_path)?.analyze()?;

let manifest =
Expand Down
37 changes: 5 additions & 32 deletions crates/metassr-build/src/server/renderer/head.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,13 @@
use anyhow::{anyhow, Result};
use lazy_static::lazy_static;
use metacall::{loaders, metacall_no_arg};
use metassr_utils::cache_dir::CacheDir;
use std::{
collections::HashMap, ffi::OsStr, path::PathBuf, sync::Mutex, thread::sleep, time::Duration,
};
use metassr_utils::{cache_dir::CacheDir, checker::CheckerState};
use std::{collections::HashMap, ffi::OsStr, path::PathBuf, sync::Mutex};

use metassr_bundler::WebBundler;

lazy_static! {
static ref IS_HEAD_SCRIPT_LOADED: Mutex<HeadSciptLoadingState> =
Mutex::new(HeadSciptLoadingState::default());
}

/// A detector for if the head is loaded or not.
#[derive(Debug)]
pub struct HeadSciptLoadingState(bool);

impl HeadSciptLoadingState {
pub fn new() -> Self {
Self(false)
}
pub fn loaded(&mut self) {
self.0 = true
}
pub fn is_loaded(&self) -> bool {
self.0
}
}

impl Default for HeadSciptLoadingState {
fn default() -> Self {
Self::new()
}
static ref IS_HEAD_SCRIPT_LOADED: Mutex<CheckerState> = Mutex::new(CheckerState::default());
}

pub struct HeadRenderer {
Expand All @@ -53,18 +28,16 @@ impl HeadRenderer {

pub fn render(&mut self, bundler: bool) -> Result<String> {
let mut guard = IS_HEAD_SCRIPT_LOADED.lock().unwrap();
if !guard.is_loaded() {
if !guard.is_true() {
if bundler {
self.bundle()?;
// TODO: remove this line
sleep(Duration::from_millis(500));
}

let _ = loaders::from_single_file(
"node",
format!("{}/head.js", self.cache_dir.dir_path().display()),
);
guard.loaded()
guard.make_true()
}
drop(guard);

Expand Down
1 change: 1 addition & 0 deletions crates/metassr-bundler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ lazy_static = "1.5.0"
metacall = "0.4.1"
metassr-utils = { path = "../metassr-utils" }
serde_json = "1.0.128"
tracing = "0.1.40"
47 changes: 20 additions & 27 deletions crates/metassr-bundler/src/bundle.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
const { rspack } = require('@rspack/core');
const path = require("path");
const path = require('path');

function safelyParseJSON(json) {
let parsed

try {
parsed = JSON.parse(json)
return JSON.parse(json)
} catch (_) {
parsed = undefined
return undefined
}

return parsed // Could be undefined!
}

let config = {

output: {
filename: "[name].js",
filename: '[name].js',
library: {
type: "commonjs2",
type: 'commonjs2',
},
publicPath: ""
publicPath: ''
},
resolve: {
extensions: ['.js', '.jsx', '.tsx', '.ts']
Expand All @@ -46,7 +42,7 @@ let config = {
preserveAllComments: false,
transform: {
react: {
runtime: "automatic",
runtime: 'automatic',
throwIfNamespace: true,
useBuiltins: false,
},
Expand All @@ -70,7 +66,7 @@ let config = {
},
transform: {
react: {
runtime: "automatic",
runtime: 'automatic',
throwIfNamespace: true,
useBuiltins: false,
},
Expand All @@ -89,9 +85,7 @@ let config = {
}
}



function web_bundling(entry, dist) {
async function web_bundling(entry, dist) {

const compiler = rspack(
{
Expand All @@ -111,19 +105,18 @@ function web_bundling(entry, dist) {

);

compiler.run((error, stats) => {
if (error) {
console.error(error);
process.exit(2);
}
if (stats && stats.hasErrors()) {
process.exitCode = 1;
}
if (!compiler || !stats) {
return;
}
return new Promise((resolve, reject) => {
return compiler.run((error, stats) => {
if (error) {
reject(error.message);
}

if (error || stats?.hasErrors()) {
reject(stats.toString("errors-only"));
}
resolve(0);
});
});

}

module.exports = {
Expand Down
90 changes: 63 additions & 27 deletions crates/metassr-bundler/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,38 @@
use anyhow::{anyhow, Result};
use lazy_static::lazy_static;
use metacall::{loaders, metacall, MetacallNull};
use std::{collections::HashMap, ffi::OsStr, marker::Sized, path::Path, sync::Mutex};
use metacall::{loaders, metacall, MetacallFuture, MetacallValue};
use metassr_utils::checker::CheckerState;
use std::{
collections::HashMap,
ffi::OsStr,
marker::Sized,
path::Path,
sync::{Arc, Condvar, Mutex},
};
use tracing::error;

lazy_static! {
static ref IS_BUNDLING_SCRIPT_LOADED: Mutex<BundleSciptLoadingState> =
Mutex::new(BundleSciptLoadingState::new());
/// A detector for if the bundling script `./bundle.js` is loaded or not. It is used to solve multiple loading script error in metacall.
static ref IS_BUNDLING_SCRIPT_LOADED: Mutex<CheckerState> = Mutex::new(CheckerState::new());

/// A simple checker to check if the bundling function is done or not. It is used to block the program until bundling done.
static ref IS_COMPLIATION_WAIT: Arc<CompilationWait> = Arc::new(CompilationWait::default());
}
static BUILD_SCRIPT: &str = include_str!("./bundle.js");
const BUNDLING_FUNC: &str = "web_bundling";

/// A detector for if the bundling script `./bundle.js` is loaded or not.
#[derive(Debug)]
pub struct BundleSciptLoadingState(bool);

impl BundleSciptLoadingState {
pub fn new() -> Self {
Self(false)
}
pub fn loaded(&mut self) {
self.0 = true
}
pub fn is_loaded(&self) -> bool {
self.0
}
/// A simple struct for compilation wait of the bundling function.
struct CompilationWait {
checker: Mutex<CheckerState>,
cond: Condvar,
}

impl Default for BundleSciptLoadingState {
impl Default for CompilationWait {
fn default() -> Self {
Self::new()
Self {
checker: Mutex::new(CheckerState::with(false)),
cond: Condvar::new(),
}
}
}

Expand Down Expand Up @@ -56,24 +60,56 @@ impl<'a> WebBundler<'a> {
}
pub fn exec(&self) -> Result<()> {
let mut guard = IS_BUNDLING_SCRIPT_LOADED.lock().unwrap();
if !guard.is_loaded() {
if !guard.is_true() {
if let Err(e) = loaders::from_memory("node", BUILD_SCRIPT) {
return Err(anyhow!("Cannot load bundling script: {e:?}"));
}
guard.loaded();
guard.make_true();
}
drop(guard);

if let Err(e) = metacall::<MetacallNull>(

fn resolve(_: Box<dyn MetacallValue>, _: Box<dyn MetacallValue>) {
let compilation_wait = &*Arc::clone(&IS_COMPLIATION_WAIT);
let mut started = compilation_wait.checker.lock().unwrap();

started.make_true();
// We notify the condvar that the value has changed
compilation_wait.cond.notify_one();
}

fn reject(err: Box<dyn MetacallValue>, _: Box<dyn MetacallValue>) {
let compilation_wait = &*Arc::clone(&IS_COMPLIATION_WAIT);
let mut started = compilation_wait.checker.lock().unwrap();

error!("Bundling rejected: {err:?}");

started.make_true();
// We notify the condvar that the value has changed
compilation_wait.cond.notify_one();
}

let future = metacall::<MetacallFuture>(
BUNDLING_FUNC,
[
serde_json::to_string(&self.targets)?,
self.dist_path.to_str().unwrap().to_owned(),
],
) {
return Err(anyhow!("Cannot running {BUNDLING_FUNC}(): {e:?}"));
)
.unwrap();

future.then(resolve).catch(reject).await_fut();

// Wait for the thread to start up.
let compilation_wait = Arc::clone(&IS_COMPLIATION_WAIT);

let mut started = compilation_wait.checker.lock().unwrap();

// Waiting till future done
while !started.is_true() {
started = Arc::clone(&IS_COMPLIATION_WAIT).cond.wait(started).unwrap();
}

// Reset checker
started.make_false();
Ok(())
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/metassr-create/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl Creator {
}
}
pub fn generate(&self) -> Result<()> {
let template = self.template.load(&self)?;
let template = self.template.load(self)?;
let root = PathBuf::from(&self.project_name);

if root.exists() {
Expand Down
30 changes: 30 additions & 0 deletions crates/metassr-utils/src/checker.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/// A simple checker state
#[derive(Debug)]
pub struct CheckerState(bool);
impl CheckerState {
pub fn new() -> Self {
Self(false)
}

pub fn with(state: bool) -> Self {
Self(state)
}

pub fn make_true(&mut self) {
self.0 = true
}

pub fn make_false(&mut self) {
self.0 = false
}

pub fn is_true(&self) -> bool {
self.0
}
}

impl Default for CheckerState {
fn default() -> Self {
Self::new()
}
}
1 change: 1 addition & 0 deletions crates/metassr-utils/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod cache_dir;
pub mod checker;
pub mod dist_analyzer;
pub mod rand;
pub mod src_analyzer;
Expand Down
7 changes: 1 addition & 6 deletions metassr-cli/src/cli/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@

use metassr_build::{client::ClientBuilder, server::ServerSideBuilder, traits::Build};

use std::{
thread::sleep,
time::{Duration, Instant},
};
use std::time::Instant;

use tracing::{debug, error};

Expand All @@ -38,8 +35,6 @@
return Err(anyhow!("Couldn't continue building process."));
}

// TODO: find a solution to remove this
sleep(Duration::from_secs(1));

if let Err(e) = ServerSideBuilder::new("", &self.out_dir, self._type.into())?.build() {
error!(
Expand All @@ -63,12 +58,12 @@
#[derive(Debug, ValueEnum, PartialEq, Eq, Clone, Copy)]
pub enum BuildingType {
/// Static-Site Generation.
SSG,

Check warning on line 61 in metassr-cli/src/cli/builder.rs

View workflow job for this annotation

GitHub Actions / clippy

name `SSG` contains a capitalized acronym

warning: name `SSG` contains a capitalized acronym --> metassr-cli/src/cli/builder.rs:61:5 | 61 | SSG, | ^^^ help: consider making the acronym lowercase, except the initial letter: `Ssg` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms = note: `#[warn(clippy::upper_case_acronyms)]` on by default
/// Server-Side Rendering.
SSR,

Check warning on line 63 in metassr-cli/src/cli/builder.rs

View workflow job for this annotation

GitHub Actions / clippy

name `SSR` contains a capitalized acronym

warning: name `SSR` contains a capitalized acronym --> metassr-cli/src/cli/builder.rs:63:5 | 63 | SSR, | ^^^ help: consider making the acronym lowercase, except the initial letter: `Ssr` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms
}

impl Into<server::BuildingType> for BuildingType {

Check warning on line 66 in metassr-cli/src/cli/builder.rs

View workflow job for this annotation

GitHub Actions / clippy

an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true

warning: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true --> metassr-cli/src/cli/builder.rs:66:1 | 66 | impl Into<server::BuildingType> for BuildingType { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: `impl From<Local> for Foreign` is allowed by the orphan rules, for more information see https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into = note: `#[warn(clippy::from_over_into)]` on by default help: replace the `Into` implementation with `From<cli::builder::BuildingType>` | 66 ~ impl From<BuildingType> for server::BuildingType { 67 ~ fn from(val: BuildingType) -> Self { 68 ~ match val { 69 ~ BuildingType::SSG => server::BuildingType::StaticSiteGeneration, 70 ~ BuildingType::SSR => server::BuildingType::ServerSideRendering, |
fn into(self) -> server::BuildingType {
match self {
Self::SSG => server::BuildingType::StaticSiteGeneration,
Expand Down
4 changes: 2 additions & 2 deletions metassr-cli/src/cli/creator.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use clap::ValueEnum;
use metassr_create;
use metassr_create::Creator as MetassrCreator;
use std::{fmt::Display, str::FromStr};
use tracing::{error, info};

Expand Down Expand Up @@ -30,7 +30,7 @@ impl Creator {

impl Exec for Creator {
fn exec(&self) -> anyhow::Result<()> {
match metassr_create::Creator::new(
match MetassrCreator::new(
&self.project_name,
&self.version,
&self.description,
Expand Down
Loading