just-js / just

the only javascript runtime to hit no.1 on techempower :fire:
https://just.billywhizz.io/
MIT License
3.65k stars 125 forks source link

"Hello World" example #47

Closed rishavs closed 2 years ago

rishavs commented 2 years ago

Hi

I tried to work out "hello World" example using the latest techempower code and there are some parts that I am unable to understand.

My code is;

const stringify = require('@stringify')
const http = require('@http')
const process = require('process')

const { createServer, responses } = http
const { sjs, attr } = stringify

const message = 'Hello, World!'
const json = { message }

function spawn (main) {
    if (just.env()['WORKER']) return main()
    const { watch, launch } = process
    const processes = []
    const cpus = parseInt(just.env().CPUS || just.sys.cpus, 10)
    for (let i = 0; i < cpus; i++) {
      just.sys.setenv('WORKER', i)
      //const proc = launch(just.args[0], ['--trace-gc', ...just.args.slice(1)])
      const proc = launch(just.args[0], just.args.slice(1))
      processes.push(proc)
      proc.stats = { user: 0, system: 0 }
    }
    return Promise.all(processes.map(p => watch(p)))
}

class Clock {
    constructor () {
      this.slots = new Map()
    }

    unset (callback, repeat = 1000) {
      const current = this.slots.get(repeat)
      if (!current) return
      current.callbacks = current.callbacks.filter(cb => cb !== callback)
      if (!current.callbacks.length) {
        just.clearTimeout(current.timer)
        this.slots.delete(repeat)
      }
    }

    set (callback, repeat = 1000) {
      let current = this.slots.get(repeat)
      if (current) {
        current.callbacks.push(callback)
        return
      }
      current = {
        callbacks: [callback],
        timer: just.setInterval(() => current.callbacks.forEach(cb => cb()), repeat)
      }
      this.slots.set(repeat, current)
    }
}

async function main() {
    const sJSON = sjs({ message: attr('string') })

    const server = createServer()
        .get('/plaintext', res => res.text(message))
        .get('/json', res => res.utf8(sJSON(json), responses.json))
        .listen('0.0.0.0', 8080)

    const clock = new Clock()
    clock.set(() => {
        server.update()
    })
}

spawn(main)
    .catch(err => just.error(err.stack))

This is working for me. But I am unable to understand the Clock class. what does it do ? What does server.update do?

Regarding spawn, I understand that each process carries the entire app (main function) in memory. every request to the server gets 1 process assigned, and every 'tick" the server processes the processes in the processes list. Is that understanding correct?

Also, I hope I don't come across as entitled, but some basic starter documentation would be great to have. The examples seem to be very out of date, and working out a simple program is quite difficult. Maybe just this Hello World sample, with good comments can be added to the main readme and act as a great starting point for new users.

billywhizz commented 2 years ago

hi @rishavs, the clock class is used to enable running multiple timers on the same schedule without having to create a new file descriptor for each one - a micro-optimization really. for your example, you could just as easily use.

just.setInterval(() => server.update(), 1000)

i may just move this logic into the http library itself or figure out a cleaner solution once i have time to look into it more.

server.update updates the Date field in the pre-generated standard headers for common responses as another micro-optimization, meaning these standard headers don't have to be re-generated on every request. calling new Date() repeatedly in a tight loop has a significant impact on perf so goal is to avoid having to do that when generating standard headers for each request.

see here and here.

yes. i plan on spending time over next few weeks on documentation and adding some type definitions to get intellisense working in VsCode etc. and writing up some tutorials and updating examples. it's in a reasonably stable state now where i think i can spend some time on this and hopefully generate some interest. let me know if you have any other suggestions or want to get involved in any way.

rishavs commented 2 years ago

Hey @billywhizz I would love to contribute. Right now though as there is no documentation, and that I am strugglingt o start out - I would be unable to add much value. That said, once you have started, and I undertand just-js better, I can chip in.

I had some suggestions regarding the structure - Maybe we can go for something like this, (which as a user, I would want for any new framework/library that I try)

Just-js being very low level would likely not be solving for many of these topics, but it might be a good idea to at least provide the recommended way of solving them (via a 3rd party library or just writing code).

Another thing, I would recommend having a Discord where the community can hang out on and ask questions. I am assuming that you would want to keep the GH issues mainly for bug reports.

billywhizz commented 2 years ago

@rishavs - thanks for the input. all good suggestions. my plan at moment is to have readme's along with each library module and in the main just-js repo and then some kind of manual/book of howtos and more advanced example applications/recipes etc.

rather than creating an enormously complex and comprehensive http framework out of the box i would prefer to keep most of the core stuff fairly bare bones and leave the higher level things to the community. i want to keep core small and simple and more oriented to folks who are interested in doing lower level systems work in JS or folks who want to build their own higher level abstractions on top of a solid foundation, with ability to reach down into lower level stuff when needed (something that is very difficult and painful with node.js).

i have used it to put a lot of useful things together for myself over past while and i find the combo of very simple c/c++ and javascript so much more pleasant to work with than Rust or Go and, if you are careful, as we can see from techempower, you can get equivalent or better perf than most/all other languages/platforms.

i created a gitter and a discord but not much action on either right now. feel free to jump in and ask some questions on there and i will check up on them regularly.

rishavs commented 2 years ago

@billywhizz Can you add a couple of text channels in your discord? I am getting this error. image

billywhizz commented 2 years ago

i know very little about discord tbh. #General seems to be set up as a text channel? Screenshot from 2022-06-09 11-26-15

rishavs commented 2 years ago

maybe I need to be invited to your server first? I think you need to share the link to join your server and only then I can access teh channels. I just created a new dummy server and the invite link looks like this https://discord.gg/Md4uJEkK

image

billywhizz commented 2 years ago

try this? https://discord.gg/aFpU6VzQ

billywhizz commented 2 years ago

@rishavs tbh i think i would prefer to just use gitter. there's already people there and discord wants me to pay to add a profile image which seems kinda scammy to me. https://gitter.im/just-js/community

rishavs commented 2 years ago

I would recommend keeping Discord around. Gitter doesn't have many users while Discord has a huge userbase which is increasing. So, for the longevity of your community Discord is important, imo.

Also, I don't think changing your avatar or the server pic is a paid feature. I am able to do it.