tag to a max-width of say 200px, the box-model will never exceed 200 pixels, although the content itself may overflow out, but the important point is that it will never exceed the width you have defined.
What is interesting is that if your content for the p tag takes up less than 200 pixels, then max-width will have no effect on it. The size will just be the amount of space that the content takes up.
This is useful with say grid layout to create responsive webpages. An image gallery that when you shrink, the image will also shrink, when you expand the viewport the image will grow but only up until the specified width.
Very good property, I approve.
Microservices Explained
Problem with Monolithic architecture
At the beginning of application development, the standard way of doing it was via a monolithic architecture. Monolithic meaning that all components of an application for example an online shopping platform would be part of a single code-base.
Component such as user-authentication, the shopping-cart, product-catalog, notification system, and payment system code will all be in a single code-base.
Cons
Every component is developed, deployed and scaled as 1 unit. This also means that the application can only be in one tech stack.
Team that works on different component of this monolithic application must be careful to not affect each other's work. In addition, when you are deploying this monolithic application the entire application must be redeployed you cannot just redeploy just one single component of the application.
If the application is large and complex, then different components will be more tangled into each other. If you want to scale then you must scale the entire applications, not only parts of components that are in demand = higher infrastructure cost.
Release process takes longer, the CI/CD pipeline will need to rebuild the entire application from the ground, component to component in order to redeploy.
Microservices
Now instead of writing one giant monolithic application you break up the application into smaller, and independent services.
How to break down the application? How many microservices to break it into? How big/small it should be? How do they communicate with each other after you split them up? These are all questions when you are developing microservices.
Microservice architecture
Well you split up the application based on business functionalities. It is something that a business or a company does in order to generate value. Business features that can stand on it's own without other.
Each microservice should be responsible for one service, one specific job. They should be self-contained and independent of each other. Which means that they can be developed, deployed, and scaled separately on their own without relying on another.
Communication between microservices
1. API calls
How do they talk to each other if they are separate applications?
The common way of doing communication is via API calls. Each of the microservices has it's own API endpoint, then the microservices can then just communicate to each other by sending HTTP request to each fo the endpoint.
This is for synchronous communication, you sent the request and expect a reply.
2. Message broker
This is for asynchronous communication, messages will sent the request to a message broker and that will be stored in a queue, then the broker will forward that message to the actual microservices.
You sent the request but the actual message can be stored in queue and without knowing exactly when you will receive a reply.
Monorepo vs Polyrepo
Now when you are writing microservices how do you store them on cloud repository? Like Github or Gitlab?
With Monolithic repository you can just slap that big application into one repo and call it a day. But whatever Microservices? There is two ways of storing it into a Git repo.
Monorepo
Having one git repository that contains many projects (the microservices).
You would have a directory for each service/project/microservice.
This makes code management and development easier, just need to clone and work only with one repo. Changes can be tracked together, tested together.
But, having these project together is might result in tight coupling of projects. All these projects can result in large repository in the end.
Polyrepo
One microservice per one repository. Own CI/CD per repository.
You can group those microservice repository together under a group for easier management.
Switching between project is tedious. Sharing resources is more difficult.
Both have advantages and disadvantages.
Caching vs CDN
Cache(ElastiCache)
Again caching is storing data that are frequently accessed into RAM so that they can be retrieved more quickly than going through a disk / a database query which takes significantly more time on CPU scale.
CDN
Content delivery network is a network of proxy servers that are placed in different geographical locations all around the world. The goal is that rather than having the user say in California make a request to a server that is in New York to request content, you place those website contents in CDN so that they can be retrieved quicker by making a request to the CDN server closer to the user.
Cache and CDN
They both share the purpose of retrieving content quicker for the user.
More about OAuth2.0 grant
What is a grant?
When you sent a request to the authorization server you will sent a field that specify the type of grant that you would want:
implicit
authorization code
client credentials
password
refresh token
Think of the grant as the "method" that you would like to interact with the server to get the access token (after all the end goal is to get an access token to interact with the API server no?), you would usually use the authorization code grant to get the access token on the behalf of the user.
You would use client credentials to get access token on behalf of the application itself, not the user.
Authorization code
This grant type is the one that you typically see when you interact with an application on the web. Say an application online twitter-tweet-auto.com that advertise itself as a free tweeting tool that help you sent out scheduled tweets, you would then use the website will redirect you to a twitter page which asks for your permission for this application (twitter-tweet-auto.com) to access your account.
You would either approve or deny the request and you would be redirected back to the site. Then the site might "log you in" in the sense that they have your access token and can provide the "service" to you on your behalf. You achieved this without giving your password and username to the website.
Client credentials
Let's say an application itself is using the service then the grant type it will need to choose is client credentials. Through this grant type you would be getting back an access token for YOUR APPLICATION not on the behalf of any user.
You would be providing your client id and client secret in the request so that the authorization server / token server and provide the access token for you after authentication yourself.
There will not be any prompt to allow or deny the access because again it is not on behalf of any user anymore.
Implicit
The access token is returned immediately without needing to go through the token server to exchange the authorization code for a valid access token.
However, this is pretty deprecated and is kinda dangerous, use authorization code instead.
Password
First of all. Why?
This is the exact reason why OAuth is created in the first place which is to avoid user provided credentials to gain access to their resources.
Well, in this grant you would provide the user's username and password in the request in order to gain the access token, but why?
yaml and JSON
JSON
Javascript object notation, is a serialization language that converts complicated objects like Linked List to a streams of bytes that can then be transmitted over the wire or be stored in memory. This is required because you can't just transmit a "Linked List" over the internet. You would do it by first converting the object into a streams of bytes (serialization), then sending the bytes to the receiver, and when the receiver receives all the bytes they can then reconstruct the bytes into the "Linked List" (deserialization).
In JSON, keys are required to be in quotations.
YAML just like JSON, or rather is a superset of JSON is also a serialization language that is popular to be used as a configuration file.
Yet another markup language
YAML files uses spaces for formatting like in Python and not tabs.
To begin a YAML file you need to put 3 dashes.
Key values are string by default so do you don't need to put it in quotation around like in JSON, you can if you want to but is not done often. String values you can enclose in double quotes, single quotes, or even no quotes at all.
---
a: 1
b: hello
c: "world"
Values of each key can be string, floating point, boolean, integers, an array, or even a nested dictionary.
Different types for YAML
---
doe: a deer a female deer
pi: 3.1415926
numbers:
- 1
- 2
- 3
nested:
lol: 1
lmafo: 2
rofl: 3
To do an array, you just put values after a dash.
To do a nested dictionary you just tab and start with key value pair again in the same indentation.
You can even do an array of dictionary like below:
---
numbers:
- lol: 3
xd: 2
- 2
- 3
In this case, numbers is a list of three elements. The first element is a dictionary that have two key-value pair. The second element is 2, and last element is 3.
One line dictionary
Dictionary can be one line if you want to:
---
nested: {hello: 3, world: 4}
Anchors and alias
Anchor is defined using & symbol. It is used to improve reusability and modularity. You will essentially define a block of configuration that you would like to reuse by using the anchor symbol.
Then where you want to reference the values within the anchor you would use the * alias symbol. It is saying look at the anchor to find the values to use for this particular block of files.
You can anchor a scalar value:
---
toggle: &toggle true
do_i_skip: *toggle
In this case, do_i_skip will also reference to the scalar value true .
You can anchor a more complex value:
---
nested_dict: &reference
- 1
- 2
- 3
- config: on
bookstack: on
file_run: on
nested_dict2: *reference
nested_dict2 will contain the same four element as nested_dict because it reference the anchor that was placed on nested_dict . The anchor will be all the values within the same tab.
A more complicated example:
---
nested_dict: &reference
- 1
- 2
- 3
- &inner_anchor
config: on
bookstack: on
file_run: on
nested_dict2: *reference
nested_dict3: *inner_anchor
Now in this case nested_dict2 is still as the same before, but nested_dict3 will be reference to a dictionary of three element. config: on, bookstack: on, file_run: on
Override anchor
Say if you want to reference the anchor but want to make just a tiny little change of the inherited values you MUST use <<: