design – Building a Microservices App — Can you give feedback on architecture?

I did some googling, and I was directed to Software Engineering to ask architecture questions. If you know of a different forum that could help me, please direct me to it

I recently started learning about microservices, and would like to build an experimental app (the backend) just for practice. I’ll explain the app requirements, and after that outline my microservices-based solutions (and some doubts/questions I have). I’d love to get your feedback, or your approach to building this app using microservices.

Please note: I am a beginner when it comes to microservices, and still learning. My solution might not be good, so I’d like to learn from you.

The App (Silly App):

The purpose of this app is to make sure users eat carrots four times a week. App admins create a carrot eating competition that starts on day x and ends 8 weeks after day x. Users can choose whether or not to participate in the competition. When a user joins the competition, they need to post a picture of themselves eating a carrot. The admin approves/rejects the picture. If approved, the carrot eating session counts towards the weekly goal, otherwise it does not. At the end of each week, participating users are billed $10 for each carrot eating session they missed (for example, if they only eat carrots two times that week, they’re billed $20). That $20 goes into a “money bucket”. At the end of two months, users who successfully ate carrots four times a week every single week divide the money in the bucket among themselves. For example, assume we have users A, B, C. User A missed all carrot eating sessions for two months (puts $40 a week in the money bucket, so $320 by the end of two months). Users B and C eat their carrots four times a week consistently for two months. So users B and C take home $320/2 = $160.

Simplification:
I wanted to start simple. Forget about money. Forget about admin approval. We can add that later. For now, let’s focus on a very simplified version of the app.

  • User can signup/login/logout to app
  • When a user signs up, they are automatically enrolled into the next carrot eating competition
  • Users can post an image of him/herself eating a carrot
  • Users can see a feed of other users images (similar to instagram, except all pics are of people eating carrots)
  • Users can access their profile – a page that displays how they’re doing in the competition: I.e,for each week, how many carrots they ate. And which weeks they failed at.
  • At any point in time, users can access a page that shows who the current winners are (i.e, users who did not miss a carrot eating session yet).

Is this an appropriate simplification to start with?

Thinking Microservices – Asynchronous Approach:

Auth Service: Responsible for Authenticating User

Database:

  • User Table: id, username, email, password

Routes:

  • POST /users/new : signup
  • POST /users/login: login
  • POST /users/signout: signout

Events:

Image Service: Responsible for Saving Images (upload to Amazon S3)

Database:

  • User Table: userId, username
  • Image Table: imageId, userId, dateUploaded, imageUrl

Routes:

  • POST /users/:userId/images: Post new image
  • GET /users/:userId/image/:imageId: Return a specific image
  • GET /images: Return all images (Feed)

Events:

  • Publishes:
    • Image:created (userId, imageId, imageUrl, dateUploaded)

Competition Service: Responsible for managing competition

Database:

  • Competition table: id, startDate, duration
  • User table: id, username, competitionId, results (see below)

Routes:

  • POST /competition: create a competition
  • GET /competition/:competitionId/users/:userId: get results for a specific user
  • GET /competition/:competitionId/users: get a list of users participating in competition (see below)
  • GET /competition/:competitionId: get a list of winners, and for each looser how many workouts they missed

Events:

  • Listens:
    • User:created
    • Image:created

In the database, user table, Results is the JSON equivalent of

results = {
   week1: {
       date: 'oct 20 2020 - oct 27 2020',
       results: ('mon oct 20 2020', 'tue oct 21 2020', 'thur oct 23 2020'),
   },
   week2: {
       date: 'oct 28 2020 - nov4 2020',
       results: ('somedate', 'somedate', 'somedate', 'somedate'),
   },
   week3: {
       date: 'nov 5 2020 - nov 12 2020',
       results: (),
   },
   ...
}

Better ideas on how to store this data appreciated

GET /competition/:competitionId returns

const results: {
 winners: ({ userId: 'jkjl'; username: 'jkljkl' }, { userId: 'jkjl'; username: 'jkljkl' });
 loosers: (
   { userId: 'kffjl'; username: 'klj'; carrotDaysMissed: 3 },
   { userId: 'kl'; username: 'kdddfj'; carrotDaysMissed: 2 }
 );
};

What do you think of this? How would you improve it? Or would you approach this from an entirely different way?

Why does Solve give me an expression with root in it for this equation?

“12.0.0 for Microsoft Windows (64-bit) (April 6, 2019)”

This can be solved by hand without too much difficulty. But

Solve({s == 8/27 ((Sqrt(1 + (3/2 t)^2))^3 - 1), t > 0}, t, Reals)

results in

{{t -> ConditionalExpression(
    Root(-16 s - 27 s^2 + 16 #1^2 + 36 #1^4 + 27 #1^6 &, 2), s > 0)}}

exalted – What happens if you give away a Artifact with a Hearthstone?

If a person has an artifact with one or more hearthstones and for some reason decide to give it away to someone else what happens? Can another exalted attune the artifact and keep the hearthstone from the previous owner in the item? Will it work just the same for the new owner?

I would appreciate references to the rules, but that is not strictly necessary. If there is no reference to the rules I want an argument for why it should be this way.

gcc – Can you please give feedback on my C++ Code?

This Code uses the cstdio include for good performance

If you write C++ code, it is better to use the C++ way of doing things. While stdio is generally slightly faster than iostreams, if printing to standard output is not the performance critical part of your program, you shouldn’t switch to printf(), as you lose all of the benefits of iostreams, like type safety and interoperability with other C++ features.

Since you tagged the question C++20, you should know that std::format is even faster than stdio at formatting output, and combines the best of both worlds.

In the code you posted, you only output string literals, so no formatting is involved and likely all three methods will perform similarly.

I already mentioned that stdio is less type safe. And indeed you have an error: scanf("%i", ...) expects a pointer to an int, not an int8_t. This means you potentially overwrite the stack here. This problem would not have happened with iostreams, although std::cin >> input will likely not give the result you expect. When reading in an integer, just use int.

Again, this is likely premature and misguided optimization. A single int8_t will not be more efficient than an int, and in fact might be less efficient. Only if you store large amounts of values, such as in an array, will it make sense to use small integer types to save memory space and bandwidth.

You print strings without n at the end. This might cause the output to not appear immediately (standard output is usually line-buffered), and the next print statement will print on the same line, which is probably not what you want.

python – Is it okay to give for loop index variables a name other than a simple x or y?

I’m currently cleaning up a web scrapping python script using selenium to download all module content from a blackboard university site.

My review question is in regards to the naming of index variables in a for loop. Currently I have the following nested for loops:

for x in range(len(modules)):


    for y in range(modules(x)('content')):

        do.something(modules(x)('content')(y)('url'))

And I am thinking of changing the loops to something more like the following:

for module in range(len(modules)):


    for content in range(len(modules(module)('content'))):

        do.something(modules(module)('content')(content)('url'))

Is this appropriate for me to do given the purpose of the loops? I have been scolded here before about something similar so wanted to be sure.

Thanks!

I’m 16, I’m stuck outside of Australia with an expired Australian passport and my mother is refusing to give me my valid one. What can I do?

My parents are divorced and still in a custody battle over my sister and I so we need signatures from both of them for me to get a passport. We got a passport earlier this year but because my dad isn’t in Australia they couldn’t give it to him so they gave it to my mum. Now she’s refusing to give me my passport. I’ve got recordings of her saying she won’t give it to me. Is there anything I can do to get my passport so I can come back home? I do have an Afghan passport but my Aussie passport and afghan passport are under different names. What can I do? Please help. I want to go home.

javascript – Why this function doesn’t wait to give its answer?

To extract some numbers from a website, I use this JS code (in a HTML page)

let getJSON = (url, callback) => {
    let xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.responseType = 'json';
    xhr.onload = () => {
        let status = xhr.status;
        if (status == 200) {
            callback(null, xhr.response);
        } else {
            callback(status);
        }
    };
    xhr.send();
};

function new_number() {
getJSON('https://qrng.anu.edu.au/API/jsonI.php?length=5&type=uint8&size=6', (err, data) => {
    if (err != null) {
        console.error(err);
    } else {
        let dat = `${data.data}`
    var dat2 = JSON.stringify(dat);
    console.log(dat2);
        return dat2;
    }
});
}

But when I call new_number(); I immediately get “undefined” but one second after the call of “console.log(dat2);” gives the right string. As if the function wants to give something right away without waiting… what should I change please ?

How can I give a druid better armor?

I asked my players OoC what sorts of treasure they’d be interested in, and the druid asked for armor. He had some pretty creative ideas about bone, turtle shells, etc. (ethically sourced, of course.)

Trouble is, the only (effective) non-metal armors in the PHB are light leather and Hide (RAI they can wear studded leather as well, though some DMs may not allow it). So I feel like I’m on my own, which I’d rather not be since I’m not all that familiar with GMing 5e.

So, my question in 2 parts:

  1. Did I miss something in the PHB or DMG that makes it make sense for Druids to have proficiency with “Light and Medium armor”, not just leather and hide? Is there, for example, dragon-scale armor (which would be perfect but doesn’t seem to be in there)?

  2. If not, and we’re down to house rules, has anyone tried bypassing the no-metal restriction by allowing powerful armor to be made from other materials, and what are the pros and cons?

network – Why do people, even programmers and geeks, seem to almost feel the urge to “give hackers a fair chance” at stealing their data?

I once heard that the author of the early NES emulator “Nesticle”, clearly a very intelligent person, baffingly used some kind of exploitable “Samba” or “SMB” server running in his home with its source code (and probably other private files/data) on it.

The result was that somebody, somehow, managed to break into it and steal the source code. This made him not want to work on the project anymore, understandably if you understand us folks who don’t do “open source” development. (Even if we give away the resulting program for free.)

An old friend of mine mentioned that he would be storing some embarrassing videos and audio recordings we made as kids, on his home “NAS”. I shuddered at the thought and asked him to please not do that, since it’s not secure. (My own copies were on encrypted disks, without any cables going into them, in a fireproof safe.)

I’ve heard numerous people talk about their “home networks” and how they make all their files available to “all their computers at home” (what kind of insane office/enterprise setups do they have at home?!), because… they must be… available… at all times? It’s unthinkable to simply use an USB stick to put the relevant file(s) on the few times you need them and physically move them to the machine in question?

In numerous other situations, I’ve noticed that people who aren’t idiots in general behave extremely strangely about data security. Even when it’s themselves that would get affected by a hack/compromise.

And it happens over and over again. Even if you constantly keep all the software updated, which is extremely rare (most people seem to not have any idea that things ever have to be updated/patched/maintained in any way), there’s just so many mistakes and arrogant assumptions made by developers. A popular database software exposed all my databases to the world without even requiring a password, even though I had set one, with my only finding out about this much later. I can only hope that nobody even bothered to try breaking into it, but it was like a cold shower when I realized that this was the case. And it was far from the only such instance.

At this point, I have zero trust left in people and developers of software/hardware. Yet people who seem to be far smarter than I still seem so incredibly casual and careless about even their most private data that I’m left wondering what I’m missing.

Why is it so crucially important to a lot of people to have “occasional convenience” over the ability to sleep at night without thinking about some blackmailer across the world fetching your private photos and personal writings from your always-on file server?

Are they just incredibly naive, in spite of having big houses with tons of computers and even (in many cases) programming/computer skills far surpassing my own? I don’t understand it.

fedora – Seems like firewalld is not honouring rich rules, to give docker container outside connection aside from ping

I’m on Fedora 32 5.7.16-200.fc32.x86_64,
with the package firewalld: firewalld-0.8.3-1.fc32.noarch,
and my Docker containers (all of them, with every image)
don’t have internet access by default, or any outside
connection aside from ping, for that matter.
( for example, I can ping by IP, but not by domain,
because I can’t reach the DNS server with a request )

I knew absolutely nothing about firewalls and firewalld
in particular before this, but I’ve been reading about it,
trying to understand the problem, and find the solution.

Besides the official firewalld documentation, I’ve been
reading about incompatibilities between Docker and firewalld,
and a bunch of other things. I also know that,
exists podman as a Docker alternative.

But for me, this is not about: ‘make it work, and DONE’;
this is about understanding, as much as I can,
WHY works when it does, and
WHY does’t work when it doesn’t.

After learning about firewalld, for me, seems correct that,
by default, the situation be like the one described above.

Now, I want to change that: I want to be able to ping
by domain, for example. When being blocked, logs from
the ping by domain says:

FINAL_REJECT: IN="$CONTAINER_INTERFACE" OUT=wlp3s0 PHYSIN=vethb53e882 MAC=XX:....:XX SRC="$CONTAINER_IP" DST=1.1.1.1 LEN=56 TOS=0x00 PREC=0x00 TTL=63 ID=37255 DF PROTO=UDP SPT=57463 DPT=53 LEN=36

I tried different things; some of them, worked, and others don’t.
But some of them, I think should work, even when it doesn’t.

Seems like firewalld is not honouring its rich rules.
As far as I understood, you put a connection in one zone
(and only one) by its interface or source, and then,
the zone rules apply for the connection:
if there are no rich rules in the zone,
the target of the zone (ACCEPT,DROP, etc)
applies for that connection
if there are rich rules, and one matchs the connection,
then that rich rule is applied to that connection.
And, the first match ALWAYS wins.

What follows, is some output from my terminal, with
different tries, and each try is labeled, saying if it worked or not,
to give the docker container the hability to ping by domain.

In my opinion, all for the tries bellow should do the trick…
some of them, are doing things that I don’t think are necessary,
like the tries that change the target of the zone to DROP:
I did it, because I thought that maybe, the default target was buggy.
So, my question is, why doesn’t work, when it doesn’t?
What is wrong?

defining variables for the container ip and container interface, to easily refer to them from now on:

CONTAINER_IP="172.18.0.2"
CONTAINER_INTERFACE="br-71fe7cc090b3"

defining a function to easily restore the firewalld conf to default, and this way, I can completely restore the firewald conf before each try, knowing that all tries act on the same initial conf:

_restore_firewalld() {
    sudo cp -Ta /usr/lib/firewalld/ /etc/firewalld/ && 
    sudo restorecon -r /etc/firewalld/ && 
    sudo firewall-cmd --complete-reload && 
    sudo firewall-cmd --set-log-denied=unicast ##to log rejects
}

WORKS on its own, from default restored firewalld conf:

$ _restore_firewalld && /
$ sudo firewall-cmd --permanent --zone=docker --add-source="$CONTAINER_IP" && 
$ sudo firewall-cmd --reload && 
success
Warning: ALREADY_SET: unicast
success
success
success

$ sudo firewall-cmd --info-zone=docker 
docker (active)
  target: ACCEPT
  icmp-block-inversion: no
  interfaces: docker0
  sources: 172.18.0.2
  services: 
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

WORKS on its own, from default restored firewalld conf:

$ _restore_firewalld && /
$ sudo firewall-cmd --permanent --zone=trusted --add-source="$CONTAINER_IP" && 
$ sudo firewall-cmd --reload && 
success
Warning: ALREADY_SET: unicast
success
success
success

$ sudo firewall-cmd --info-zone=trusted 
trusted (active)
  target: ACCEPT
  icmp-block-inversion: no
  interfaces: 
  sources: 172.18.0.2
  services: 
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

WORKS on its own, from default restored firewalld conf:

$ _restore_firewalld && /
$ sudo firewall-cmd --permanent --zone=docker --add-interface="$CONTAINER_INTERFACE" && 
$ sudo firewall-cmd --reload && 
success
Warning: ALREADY_SET: unicast
success
success
success

$ sudo firewall-cmd --info-zone=docker 
docker (active)
  target: ACCEPT
  icmp-block-inversion: no
  interfaces: br-71fe7cc090b3 docker0
  sources: 
  services: 
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

WORKS on its own, from default restored firewalld conf:

$ _restore_firewalld && /
$ sudo firewall-cmd --permanent --zone=trusted --add-interface="$CONTAINER_INTERFACE" && 
$ sudo firewall-cmd --reload && 
success
Warning: ALREADY_SET: unicast
success
success
success

$ sudo firewall-cmd --info-zone=trusted 
trusted (active)
  target: ACCEPT
  icmp-block-inversion: no
  interfaces: br-71fe7cc090b3
  sources: 
  services: 
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

WORKS on its own, from default restored firewalld conf:

$ _restore_firewalld && /
$ sudo firewall-cmd --permanent --zone=public --set-target=ACCEPT && 
$ sudo firewall-cmd --permanent --zone=public --add-source="$CONTAINER_IP" && 
$ sudo firewall-cmd --reload && 
success
Warning: ALREADY_SET: unicast
success
success
success

$ sudo firewall-cmd --info-zone=public 
success
public (active)
  target: ACCEPT
  icmp-block-inversion: no
  interfaces: 
  sources: 172.18.0.2
  services: dhcpv6-client mdns ssh
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

DOES NOT WORK on its own, from default restored firewalld conf:

$ _restore_firewalld && /
$ sudo firewall-cmd --permanent --zone=docker --add-rich-rule="rule family=ipv4 source address="$CONTAINER_IP" accept" && 
$ sudo firewall-cmd --reload
success
Warning: ALREADY_SET: unicast
success
success
success

$ sudo firewall-cmd --info-zone=docker 
docker (active)
  target: ACCEPT
  icmp-block-inversion: no
  interfaces: docker0
  sources: 
  services: 
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
    rule family="ipv4" source address="172.18.0.2" accept

DOES NOT WORK on its own, from default restored firewalld conf:

$ _restore_firewalld && /
$ sudo firewall-cmd --permanent --zone=public --add-rich-rule="rule family=ipv4 source address="$CONTAINER_IP" accept" && 
$ sudo firewall-cmd --reload
success
Warning: ALREADY_SET: unicast
success
success
success

$ sudo firewall-cmd --info-zone=public 
public
  target: default
  icmp-block-inversion: no
  interfaces: 
  sources: 
  services: dhcpv6-client mdns ssh
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
    rule family="ipv4" source address="172.18.0.2" accept

DOES NOT WORK on its own, from default restored firewalld conf:

$ _restore_firewalld && /
$ sudo firewall-cmd --permanent --zone=public --add-source="$CONTAINER_IP" && 
$ sudo firewall-cmd --permanent --zone=public --add-rich-rule="rule family=ipv4 source address="$CONTAINER_IP" accept" && 
$ sudo firewall-cmd --reload
success
Warning: ALREADY_SET: unicast
success
success
success
success

$ sudo firewall-cmd --info-zone=public 
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: 
  sources: 172.18.0.2
  services: dhcpv6-client mdns ssh
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
    rule family="ipv4" source address="172.18.0.2" accept

DOES NOT WORK on its own, from default restored firewalld conf:

$ _restore_firewalld && /
$ sudo firewall-cmd --permanent --zone=public --set-target=DROP && 
$ sudo firewall-cmd --permanent --zone=public --add-rich-rule="rule family=ipv4 source address="$CONTAINER_IP" accept" && 
$ sudo firewall-cmd --reload
success
Warning: ALREADY_SET: unicast
success
success
success
success

$ sudo firewall-cmd --info-zone=public 
public
  target: DROP
  icmp-block-inversion: no
  interfaces: 
  sources: 
  services: dhcpv6-client mdns ssh
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
    rule family="ipv4" source address="172.18.0.2" accept

DOES NOT WORK on its own, from default restored firewalld conf:

$ _restore_firewalld && /
$ sudo firewall-cmd --permanent --zone=public --set-target=DROP && 
$ sudo firewall-cmd --permanent --zone=public --add-source="$CONTAINER_IP" && 
$ sudo firewall-cmd --permanent --zone=public --add-rich-rule="rule family=ipv4 source address="$CONTAINER_IP" accept" && 
$ sudo firewall-cmd --reload
success
Warning: ALREADY_SET: unicast
success
success
success
success
success

$ sudo firewall-cmd --info-zone=public 
public (active)
  target: DROP
  icmp-block-inversion: no
  interfaces: 
  sources: 172.18.0.2
  services: dhcpv6-client mdns ssh
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
    rule family="ipv4" source address="172.18.0.2" accept

DOES NOT WORK on its own, from default restored firewalld conf:

$ _restore_firewalld && /
$ sudo firewall-cmd --permanent --zone=public --add-interface="$CONTAINER_INTERFACE" && 
$ sudo firewall-cmd --permanent --zone=public --add-source="$CONTAINER_IP" && 
$ sudo firewall-cmd --permanent --zone=public --add-rich-rule="rule family=ipv4 source address="$CONTAINER_IP" accept" && 
$ sudo firewall-cmd --reload
success
Warning: ALREADY_SET: unicast
success
success
success
success
success

$ sudo firewall-cmd --info-zone=public 
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: br-71fe7cc090b3
  sources: 172.18.0.2
  services: dhcpv6-client mdns ssh
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
    rule family="ipv4" source address="172.18.0.2" accept