CodeHowlerMonkey / hitfactor.info

HitFactor.info -- Howler Monkey Classifiers
https://www.hitfactor.info
11 stars 4 forks source link

Clubs endpoint #37

Closed pzsette closed 5 months ago

pzsette commented 7 months ago

I've implement this logic to retrieve all clubs ids and names from classifiers. Idk if this could be ok

pzsette commented 6 months ago

@CodeHowlerMonkey I've add memoizing to the getClubs method, It seems working but I've done it more looking at other endpoints rather than fully understanding the badLazy. Could you please explain me how it works ?

CodeHowlerMonkey commented 6 months ago

@pzsette

badLazy is older function that used Promises, that I got rid of, Promises turned out to be a bad idea for marking things as incomplete. Try pulling main and merging it into your branch, you should be able to easily refactor things into using lazy -- it's very similar, but isn't using promises.

You need to pull main from the my repo, so first you need to add it as a remote to yours, should be something like:

git add remote monkey https://github.com/CodeHowlerMonkey/hitfactorlol.git
git fetch monkey main
git merge monkey/main

It's easier to explain how lazy() works first. Basically lazy() is a utility/helper function, that accepts your function as it's argument, it then "wraps it" in order to store the first computation result in it's CAPTURED state -- a feature of language that allows you to use external variables in the function, by saving a reference to them. Some languages do it explicitly, like Ruby IIRC, others just capture everything that you use inside of the function/lambda body.

The helper use this, and is also technically a HOF - Higher Order Function, which is just a fancy name for a function that returns a function.

I'll mention you on the code and comment on it step by step

For this PR your next step is to pull, resolve conflicts and use lazy and no async/await.

If you want to know more about why promises and async/await were bad idea and how different is badLazy from lazy -- let me know

CodeHowlerMonkey commented 6 months ago

Huh, thought I could just comment on files, ok, so with old cache in file commented code removed this is what lazy looks like:

export const lazy = (resolver, cachePath) => {
  let _result = null;

  return () => {
    if (_result) {
      return _result;
    } 
    _result = resolver();
    return _result;
  };
};

_result is a variable crated inside of the lazy() function body, this is where we will store the result. In normal function it wouldn't work, because after you return from it -- all its internal state/variables are lost, but because this is a HOF, and we're returning a function from our function that USES the _result -- it will stay CAPTURED and will retain its value.

so as you can see we return a newly created function, that function is the WRAPPER for the function that was supplied as an argument to the lazy (it is captured by the context too).

Now for our wrapper function both _result and resolver are just variables. It doesn't care where they came from, it can use them no problem. So we look into _result to check if it was set, if it was already -- we simply immediately return that. If not -- then we call the resolver. Whatever resolver returns -- we set it into the _result and return that.

Now, because _result isn't a variable inside of our wrapper, but instead was captured BY REFERENCE in the context -- it will retain its value next time the wrapper is called. And that's how we lazily memoize the result of an expensive computation.

badLazy was doing pretty much the same thing, but instead of manually explicitly setting a variable once the value for it was computed -- it used Promise and it's ability to track its state.

pzsette commented 6 months ago

@CodeHowlerMonkey replaced badLazy with new lazy

pzsette commented 6 months ago

If you want to know more about why promises and async/await were bad idea and how different is badLazy from lazy -- let me know

If you have time to do it, would be great

CodeHowlerMonkey commented 5 months ago

needs to be redone using mongo, closing this PR

pzsette commented 5 months ago

can I take charge of mongo implementation ? @CodeHowlerMonkey

CodeHowlerMonkey commented 5 months ago

@pzsette absolutely, all PRs are welcome.

You would need to have mongo running somewhere and hydrate it manually with npm run hydrate though

pzsette commented 5 months ago

Do you still want to keep the caching mechanism through HOF ?

CodeHowlerMonkey commented 5 months ago

Do you still want to keep the caching mechanism through HOF ?

For clubs we should probably create new collection and hydrate it in the hydration script. It would need to go through scores and select distinct clubs, so probably gonna be expensive aggregation.

It would need to capture all member numbers in a $group too.

Honestly it's pretty complicated stuff, and you would need to learn a lot about mongo to make it right.

pzsette commented 5 months ago

I can try, with a bit of help if its ok for otherwise i can do something else