tag:blogger.com,1999:blog-17625249821744906392024-03-05T15:14:34.126-08:00Adam Nagy's blogA mostly JavaScript blog about my experiences with the platform and the language.
https://nagyadam2092.github.io/Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.comBlogger58125tag:blogger.com,1999:blog-1762524982174490639.post-30210734982885586242024-01-02T23:37:00.000-08:002024-01-02T23:37:34.246-08:00Apache Kafka overview<p>Apache Kafka is a distributed event streaming platform designed to handle high volume real-time data feeds. <a class="tooltip-target" data-citationid="08c3fc17-46cc-b178-d173-a10181530ae1-10-group" h="ID=SERP,5026.1" href="https://kafka.apache.org/20/documentation/streams/architecture">It’s highly scalable, durable, and fault-tolerant</a>. Here’s a brief overview of its architecture and components:</p><div class="content" tabindex="0"><div class="ac-container ac-adaptiveCard" id="entity-image-top"><div class="ac-textBlock"><h2>Brokers</h2><p><span style="color: black;"><a class="tooltip-target" data-citationid="08c3fc17-46cc-b178-d173-a10181530ae1-14-group" h="ID=SERP,5026.1" href="https://kafka.apache.org/20/documentation/streams/architecture">A Kafka cluster consists of one or more servers known as brokers, which manage the storage and transportation of messages</a>. <a class="tooltip-target" data-citationid="08c3fc17-46cc-b178-d173-a10181530ae1-16-group" h="ID=SERP,5026.1" href="https://kafka.apache.org/20/documentation/streams/architecture">Each broker can handle terabytes of messages without performance impact</a>.</span></p><h2>Topics</h2><p>Topics are the primary unit of data in Kafka. <a class="tooltip-target" data-citationid="08c3fc17-46cc-b178-d173-a10181530ae1-20-group" h="ID=SERP,5026.1" href="https://kafka.apache.org/20/documentation/streams/architecture">They’re similar to tables in a database and are used to categorize data</a>. <a class="tooltip-target" data-citationid="08c3fc17-46cc-b178-d173-a10181530ae1-22-group" h="ID=SERP,5026.1" href="https://kafka.apache.org/20/documentation/streams/architecture">Producers write data to topics and consumers read from them</a>.</p><h2>Partitions</h2><p>Each topic in Kafka is split into one or more partitions. <a class="tooltip-target" data-citationid="08c3fc17-46cc-b178-d173-a10181530ae1-28-group" h="ID=SERP,5026.1" href="https://kafka.apache.org/20/documentation/streams/architecture">Partitions allow for data to be parallelized across the Kafka cluster, enabling greater scalability</a>.</p><h2>Producers and Consumers</h2><p><span style="color: black;"><a class="tooltip-target" data-citationid="08c3fc17-46cc-b178-d173-a10181530ae1-34-group" h="ID=SERP,5026.1" href="https://kafka.apache.org/20/documentation/streams/architecture">Producers publish data to Kafka topics, while consumers read this data</a>. <a class="tooltip-target" data-citationid="08c3fc17-46cc-b178-d173-a10181530ae1-36-group" h="ID=SERP,5026.1" href="https://kafka.apache.org/20/documentation/streams/architecture">Kafka ensures that data within each partition is consumed in the order it was produced</a><a aria-label="9: Producers publish data to Kafka topics, while consumers read this data910" class="ac-anchor sup-target" data-citationid="08c3fc17-46cc-b178-d173-a10181530ae1-36" h="ID=SERP,5026.1" href="https://www.javatpoint.com/apache-kafka-consumer-and-consumer-groups" target="_blank"><sup>9</sup></a>.</span></p><h2>Scalability</h2><p><span style="color: black;"><a class="tooltip-target" data-citationid="08c3fc17-46cc-b178-d173-a10181530ae1-40-group" h="ID=SERP,5026.1" href="https://kafka.apache.org/20/documentation/streams/architecture">Kafka is highly scalable, both horizontally (adding more machines) and vertically (adding more power to existing machines), accommodating growing data needs without sacrificing performance</a>.</span></p><h2>High Availability</h2><p><span style="color: black;"><a class="tooltip-target" data-citationid="08c3fc17-46cc-b178-d173-a10181530ae1-44-group" h="ID=SERP,5026.1" href="https://kafka.apache.org/20/documentation/streams/architecture">Kafka guarantees high availability through features like replication and partitioning</a>. <a class="tooltip-target" data-citationid="08c3fc17-46cc-b178-d173-a10181530ae1-46-group" h="ID=SERP,5026.1" href="https://kafka.apache.org/20/documentation/streams/architecture">It can recover quickly from failures, ensuring reads and writes are always available</a>.</span></p><h2>Security</h2><p><span style="color: black;"><a class="tooltip-target" data-citationid="08c3fc17-46cc-b178-d173-a10181530ae1-50-group" h="ID=SERP,5026.1" href="https://kafka.apache.org/20/documentation/streams/architecture">Kafka supports features like authentication, authorization, and encryption to ensure data security</a>. <a class="tooltip-target" data-citationid="08c3fc17-46cc-b178-d173-a10181530ae1-52-group" h="ID=SERP,5026.1" href="https://kafka.apache.org/20/documentation/streams/architecture">It also provides audit logs to track activities</a>.</span></p><h2>Kafka Streams</h2><p><span style="color: black;"><a class="tooltip-target" data-citationid="08c3fc17-46cc-b178-d173-a10181530ae1-56-group" h="ID=SERP,5026.1" href="https://kafka.apache.org/documentation/streams/" target="_blank">Kafka Streams is a client library for building applications and microservices where the input and output data are stored in Kafka clusters</a>. <a class="tooltip-target" data-citationid="08c3fc17-46cc-b178-d173-a10181530ae1-58-group" h="ID=SERP,5026.1" href="https://kafka.apache.org/20/documentation/streams/architecture" target="_blank">It simplifies application development by leveraging Kafka’s native capabilities</a><a aria-label="1: Kafka Streams is a client library for building applications and microservices where the input and output data are stored in Kafka clusters2" class="ac-anchor sup-target" data-citationid="08c3fc17-46cc-b178-d173-a10181530ae1-58" h="ID=SERP,5026.1" href="https://kafka.apache.org/20/documentation/streams/architecture" target="_blank"><sup>1</sup></a>. It is very much like RXJS's Observables, based on the same stream based operational approach to handle data changes over time.</span></p><h2>Kafka Connect and Kafka ksqlDB</h2><p>Kafka Connect is a tool for streaming data between Kafka and other data systems. Kafka ksqlDB, on the other hand, is a database purpose-built for stream processing applications, allowing you to build real-time systems on a SQL-like interface.</p><h2>Caching, Event-Driven Architecture, Event Sourcing, and Sharding</h2><p>Kafka supports caching for faster data retrieval. Its event-driven architecture ensures that actions are triggered by events. Event sourcing is a technique where changes to application state are stored as a sequence of events. Sharding, a type of database partitioning, is also used in Kafka for distributing data across different databases or servers.</p><p>In conclusion, Apache Kafka is a robust and versatile platform that can handle real-time data streaming at a large scale. Its architecture and components work together to ensure high performance, scalability, and reliability.</p></div><div aria-hidden="true" class="ac-horizontal-separator"></div></div><cib-overlay></cib-overlay></div>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-40443228518194927832023-12-11T08:01:00.000-08:002023-12-11T08:01:15.399-08:00Load balancing strategies<p> Load balancing is crucial in distributing incoming network traffic across multiple servers or resources to ensure efficient utilization, optimize resource usage, and prevent overload on any single server. Several load balancing strategies exist, each suited for specific scenarios:</p><p></p><ul style="text-align: left;"><li><b>Round Robin</b>: Requests are distributed sequentially among servers in a circular order. It's simple and ensures an equal distribution of load but might not consider the server's current load or capacity.</li><li><b>Least Connections</b>: Traffic is directed to the server with the fewest active connections. This strategy ensures that the load is distributed to the least loaded servers, promoting better resource utilization.</li><li><b>Weighted Round Robin</b>: Servers are assigned weights, specifying their capacity or processing power. Requests are then distributed based on these weights, allowing more traffic to higher-capacity servers.</li><li><b>IP Hashing</b>: The client's IP address determines which server receives the request. This ensures that requests from the same client are consistently sent to the same server, aiding session persistence.</li><li><b>Least Response Time</b>: Requests are directed to the server that currently has the shortest response time or the fastest processing capability. This strategy optimizes performance for end users.</li><li><b>Resource-based Load Balancing</b>: Takes into account server resource utilization metrics (CPU, memory, etc.) and directs traffic to servers with available resources, preventing overload and maximizing performance.</li><li><b>Dynamic Load Balancing Algorithms</b>: These algorithms adapt in real-time to changing server conditions. They can factor in various metrics like server health, latency, and throughput to dynamically adjust traffic distribution.</li><li><b>Content-based or Application-aware Load Balancing</b>: Analyzes the content or context of requests to intelligently route traffic. For instance, it can direct video streaming requests to servers optimized for video processing.</li></ul><p></p>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-79540061076292169192023-12-11T07:47:00.000-08:002023-12-11T07:47:56.450-08:00GCP services with examples<p>Similarly to the previous post, writing about GCP as well.</p><p></p><ul style="text-align: left;"><li>Compute Engine:</li><ul><li>Example: Similar to Amazon EC2, Compute Engine allows you to create and run virtual machines. You might use it to deploy and manage instances for various purposes like web hosting, application development, or machine learning tasks.</li></ul><li>Cloud Storage:</li><ul><li>Example: Storing and serving multimedia content for a content management system. Cloud Storage offers scalable object storage, ideal for hosting images, videos, backups, and large datasets used by applications.</li></ul><li>Cloud SQL:</li><ul><li>Example: Running a managed MySQL or PostgreSQL database for a retail application. Cloud SQL provides a fully managed relational database service, handling backups, replication, and maintenance tasks.</li></ul><li>Cloud Functions:</li><ul><li>Example: Implementing event-driven serverless functions for real-time data processing. You might use Cloud Functions to trigger actions in response to events like file uploads, database changes, or HTTP requests.</li></ul><li>Cloud Firestore / Cloud Bigtable:</li><ul><li>Example: Building a scalable database for a real-time chat application. Firestore offers a flexible, scalable NoSQL database for storing and syncing data across devices, while Bigtable is suitable for high-throughput, low-latency workloads like time-series data or machine learning.</li></ul><li>Cloud Pub/Sub:</li><ul><li>Example: Creating a message queuing system for handling data processing tasks. Pub/Sub provides reliable, scalable messaging between independent applications or microservices.</li></ul><li>Cloud CDN (Content Delivery Network):</li><ul><li>Example: Accelerating content delivery for a global news website. Cloud CDN caches content at Google's globally distributed edge points of presence, reducing latency for users accessing articles, images, and videos.</li></ul><li>Cloud Dataflow:</li><ul><li>Example: Processing and analyzing large datasets in real-time. Dataflow helps to build and execute data processing pipelines for tasks like ETL (Extract, Transform, Load), analytics, and batch processing.</li></ul><li>Google Kubernetes Engine (GKE):</li><ul><li>Example: Managing and orchestrating containerized applications at scale. GKE automates the deployment, scaling, and management of containerized applications using Kubernetes.</li></ul><li>Virtual Private Cloud (VPC):</li><ul><li>Example: Creating isolated networks for different projects or departments within a company. VPC allows you to define and control a virtual network, including IP ranges, subnets, and firewall rules.</li></ul></ul><p></p>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-75484486829512171822023-12-11T07:42:00.000-08:002023-12-11T07:42:22.616-08:00AWS services with examples<p>It's always hard for me to remember all the abbreviations for all the AWS services, so I tried to collect the most popular ines in this blogpost.</p><p></p><ul style="text-align: left;"><li>Amazon EC2 (Elastic Compute Cloud):</li><ul><li>Example: Imagine building a scalable web application. You can use EC2 to deploy virtual servers (instances) to run your application. You might use different instance types for web servers, application servers, and databases, scaling them based on demand.</li></ul><li>Amazon S3 (Simple Storage Service):</li><ul><li>Example: Storing and serving user-uploaded files for a social media platform. S3 provides durable object storage. You might store user profile pictures, videos, and other media files and serve them directly to users.</li></ul><li>Amazon RDS (Relational Database Service):</li><ul><li>Example: Hosting a relational database like MySQL, PostgreSQL, or SQL Server for an e-commerce site. RDS manages the database operations, allowing you to focus on your application without worrying about infrastructure management.</li></ul><li>Amazon Lambda:</li><ul><li>Example: Building a serverless backend for a mobile app. Lambda enables running code without provisioning or managing servers. You might use it to handle user authentication, process data, or trigger actions based on events.</li></ul><li>Amazon DynamoDB:</li><ul><li>Example: Implementing a highly scalable NoSQL database for a gaming application. DynamoDB offers low-latency data access and can handle massive amounts of traffic, making it suitable for gaming leaderboards or storing player data.</li></ul><li>Amazon SQS (Simple Queue Service) and Amazon SNS (Simple Notification Service):</li><ul><li>Example: Building a decoupled system for an e-commerce platform. SQS allows asynchronous communication between different components of the system, while SNS can be used to send notifications about orders or updates to interested parties.</li></ul><li>Amazon CloudFront:</li><ul><li>Example: Accelerating content delivery for a global video streaming service. CloudFront is a content delivery network (CDN) that caches content in edge locations worldwide, reducing latency for users accessing the video content.</li></ul><li>Amazon Kinesis:</li><ul><li>Example: Processing and analyzing streaming data from IoT devices. Kinesis allows you to collect, process, and analyze real-time data streams at scale, making it ideal for IoT applications, log processing, or real-time analytics.</li></ul><li>Amazon ECS (Elastic Container Service) and Amazon EKS (Elastic Kubernetes Service):</li><ul><li>Example: Orchestrating containerized applications. ECS and EKS help manage Docker containers at scale. You might use these services to deploy microservices for a distributed application architecture.</li></ul><li>Amazon VPC (Virtual Private Cloud):</li><ul><li>Example: Creating a private network within AWS. VPC enables you to launch AWS resources into a virtual network, providing control over the network configuration, including IP address ranges, subnets, and routing.</li></ul></ul><p></p>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-33744706868027235422023-12-11T07:18:00.000-08:002023-12-11T07:18:58.248-08:00Message queues vs publish/subscribe<p>Message queues and publish/subscribe are both messaging patterns used in distributed systems to facilitate communication between different components or services. While they serve similar purposes, they have distinct characteristics.</p><p>Message Queue:</p><p>A message queue is a communication mechanism where messages are stored in a queue until they are consumed by a receiving component. It follows a point-to-point communication model, where a sender pushes a message into a queue, and a single receiver retrieves and processes it. Once a message is consumed, it's typically removed from the queue. Message queues often prioritize reliable delivery, ensuring that messages are not lost even if the receiver is temporarily unavailable.</p><p>Publish/Subscribe (Pub/Sub):</p><p>Pub/Sub is a messaging pattern where senders (publishers) distribute messages to multiple receivers (subscribers) without the senders specifically targeting any subscriber. Publishers categorize messages into topics or channels, and subscribers express interest in receiving messages from particular topics. When a publisher sends a message to a topic, all subscribers interested in that topic receive a copy of the message. Pub/Sub allows for scalable and flexible communication between components and enables a one-to-many or many-to-many messaging model.</p><p>Key Differences:</p><p></p><ul style="text-align: left;"><li>Communication Model:</li><ul><li>Message Queue: Point-to-point communication between a single sender and a single receiver.</li><li>Pub/Sub: Many-to-many or one-to-many communication, where multiple subscribers receive messages from publishers.</li></ul><li>Message Handling:</li><ul><li>Message Queue: Messages are stored in a queue until consumed by a single receiver.</li><li>Pub/Sub: Messages are broadcasted to multiple subscribers interested in specific topics without being stored in queues.</li></ul><li>Relationships:</li><ul><li>Message Queue: Direct relationship between sender and receiver.</li><li>Pub/Sub: Decoupled relationship; publishers and subscribers are independent of each other.</li></ul><li>Message Retention:</li><ul><li>Message Queue: Emphasizes on ensuring that messages are not lost even if the receiver is temporarily unavailable.</li><li>Pub/Sub: Subscribers might miss messages if they are not actively subscribed when the message is published.</li></ul></ul><p></p>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-19926746015417461212023-11-22T23:32:00.000-08:002023-11-22T23:32:42.059-08:00My #1 productivity hack - Google Calendar default email reminders<p>I'd like to share a super simple trick, that might or might not work for you - which is essential in my life to organize my personal and work events. All hail <i>Google calendar default email reminder</i>.</p><p>If you're juggling a busy schedule like I am, Google Calendar's default email reminders are a game-changer. Seriously, this feature saves me so much hassle. You can customize reminders for all your events, ensuring nothing slips through the cracks.</p><p>What I love most is how easy it is to set up. Just head to settings, tweak your preferences, and voila! You can get an email nudge whenever you need it, whether it's a day before or just an hour prior to your event.</p><p>Trust me, relying on these default reminders has made my life a whole lot easier. No more frantic manual setting of reminders for each event—I just set it and forget it. It's like having a personal assistant keeping track of everything for me.</p><p>Honestly, it's not just a notification feature; it's a productivity hack. It frees up mental space, letting me focus on what I need to do without constantly worrying about missing important stuff. Give it a shot; you'll thank yourself later!</p><p>Setting default email reminders proves immensely beneficial in managing a busy schedule. It eradicates the need to manually set reminders for each event, saving time and ensuring no event goes unnoticed. The simplicity of configuring these reminders simplifies the organizational process for users, fostering a more efficient workflow.</p><p>This feature fosters productivity by reducing the mental load of remembering every event. Users can rely on the system to prompt them at designated times, allowing them to focus on the tasks at hand without worrying about missing appointments or deadlines.</p><p>The only downside of this approach is that your email client can get pretty chatty. But that also means, you're living a busy life! So all in all, this is my best approach to manage all of these events (e.g. birthdays are there too haha), but if you know a better way to do it, let me know!</p><p>Learn more about it <a href="https://support.google.com/calendar/answer/37242?hl=en&co=GENIE.Platform=Desktop" rel="nofollow" target="_blank">here</a>!</p>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-52012946536614681112023-10-09T08:26:00.003-07:002023-10-09T08:27:22.633-07:00Neural networks basics watchlist<p></p><ul style="text-align: left;"><li><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/aircAruvnKk?si=N2i5vHc1zU1toBM6" title="YouTube video player" width="560"></iframe><br /><a href="https://www.youtube.com/watch?v=aircAruvnKk&list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi" target="_blank">link to playlist</a></li><li><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/VMj-3S1tku0?si=l6eSBXnyb8TjTYA3" title="YouTube video player" width="560"></iframe><br /><a href="https://www.youtube.com/watch?v=VMj-3S1tku0&list=PLAqhIrjkxbuWI23v9cThsA9GvCAUhRvKZ" target="_blank">link to playlist</a></li></ul><p></p>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-27503190252531633292023-10-04T03:18:00.004-07:002023-10-04T03:18:30.925-07:00My VSCode TypeScript prototyping setup<p> .vscode/launch.json</p><div style="background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, "Courier New", monospace; font-size: 12px; line-height: 18px; white-space: pre;"><div>{</div><div> <span style="color: #6a9955;">// Use IntelliSense to learn about possible attributes.</span></div><div> <span style="color: #6a9955;">// Hover to view descriptions of existing attributes.</span></div><div> <span style="color: #6a9955;">// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387</span></div><div> <span style="color: #9cdcfe;">"version"</span>: <span style="color: #ce9178;">"0.2.0"</span>,</div><div> <span style="color: #9cdcfe;">"configurations"</span>: [</div><div> {</div><div> <span style="color: #9cdcfe;">"type"</span>: <span style="color: #ce9178;">"node"</span>,</div><div> <span style="color: #9cdcfe;">"request"</span>: <span style="color: #ce9178;">"launch"</span>,</div><div> <span style="color: #9cdcfe;">"name"</span>: <span style="color: #ce9178;">"Debug TS"</span>,</div><div> <span style="color: #9cdcfe;">"program"</span>: <span style="color: #ce9178;">"${workspaceFolder}/index.ts"</span>,</div><div> <span style="color: #9cdcfe;">"preLaunchTask"</span>: <span style="color: #ce9178;">"tsc: build - tsconfig.json"</span>,</div><div> <span style="color: #9cdcfe;">"outFiles"</span>: [<span style="color: #ce9178;">"${workspaceFolder}/out/**/*.js"</span>]</div><div> }</div><div> ]</div><div> }</div><br /></div><p>tsconfig.json</p><div style="background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, "Courier New", monospace; font-size: 12px; line-height: 18px; white-space: pre;"><div>{</div><div> <span style="color: #9cdcfe;">"compilerOptions"</span>: {</div><div> <span style="color: #9cdcfe;">"target"</span>: <span style="color: #ce9178;">"ES2022"</span>,</div><div> <span style="color: #9cdcfe;">"module"</span>: <span style="color: #ce9178;">"commonjs"</span>,</div><div> <span style="color: #9cdcfe;">"outDir"</span>: <span style="color: #ce9178;">"out"</span>,</div><div> <span style="color: #9cdcfe;">"sourceMap"</span>: <span style="color: #569cd6;">true</span></div><div> }</div><div>}</div></div>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-77247825262883167722023-03-05T00:41:00.000-08:002023-03-05T00:41:00.613-08:00JavaScript infinite streams<p>This post was heavily inspired by this post: <a href="https://functionalprogramming.medium.com/a-complex-guide-to-understanding-javascript-es6-generators-131eeeee46b8" target="_blank">Infinite Data structures in Javascript</a> (author: <a href="https://functionalprogramming.medium.com/" target="_blank">Dimitris Papadimitriou</a>)</p><p>After reading the article, I also wanted to have the bare minimum, and most simple implementation of a Stream - and surprisingly, it is very easy (in terms of code), but also, kinda complicated. Kind of the sweetspot I really like to learn about!</p><p><script src="https://gist.github.com/nagyadam2092/595d2da4624209e22e5f13bef0a36596.js"></script></p><p>In this implementation, we add a <span style="font-family: courier;">filter</span> method to the <span style="font-family: courier;">stream</span> object, which takes a predicate function <span style="font-family: courier;">pred</span> and returns a new <span style="font-family: courier;">stream</span> object with only the elements that pass the predicate. If the current value passes the predicate, then the resulting stream will include the current value and the result of calling filter on the next property. Otherwise, the resulting stream will only include the result of calling <span style="font-family: courier;">filter</span> on the next property. If there is no <span style="font-family: courier;">next</span> property, then the <span style="font-family: courier;">emptyStream</span> object is returned.</p><p>The resulting mappedStream is a stream of strings with the same structure as the original stream, but with each element converted to a string. The resulting filteredStream is a stream with only the elements that are greater than 1.</p><p><br /></p>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-17003145784378496342023-03-05T00:29:00.003-08:002023-03-05T00:29:40.038-08:00What's wrong with eager evaluation? (And why you should use fp-ts/Fluture for that)<p>Eager evaluation in JavaScript Promises can lead to several problems. Eager evaluation means that a Promise's executor function is executed immediately when the Promise is created, rather than when it is needed later on. Here are some potential issues with eager evaluation:</p><p>Increased resource usage: If the Promise's executor function performs a resource-intensive operation, eager evaluation can cause unnecessary resource usage. For example, if the Promise is used to fetch data from a server, eager evaluation would mean that the fetch operation is performed immediately, even if the data is not needed until later.</p><p></p><ul style="text-align: left;"><li>Unnecessary blocking: If the Promise's executor function performs a blocking operation (such as a long-running loop), eager evaluation can cause unnecessary blocking of the main thread. This can lead to unresponsive user interfaces and other performance issues.</li><li>Wasted work: If the Promise's executor function performs work that is not needed (for example, if it fetches data that is never used), eager evaluation can result in wasted work and unnecessary network traffic.</li><li>Race conditions: Eager evaluation can also lead to race conditions, where multiple Promises are created but only one of them is needed. This can result in unnecessary resource usage and can make code harder to reason about.</li></ul><p></p><p>To avoid these problems, it's generally better to use lazy evaluation with Promises. In lazy evaluation, the Promise's executor function is only executed when the Promise is needed (for example, when it is passed to a then() method or when it is awaited in an async/await function). This approach allows for more efficient use of resources and can help prevent performance issues.</p><p>The fp-ts library provides several abstractions and functions that can help avoid the problems associated with eager evaluation in Promises. For example, the type <span style="font-family: courier;">Task </span><span style="font-family: inherit;">is essentially a Promise wrapped in a function, allowing you to control when it's executed, therefore it's considered "lazy".</span></p><p><span style="font-family: courier;">import { task } from 'fp-ts/lib/Task'</span></p><p></p><p><span style="font-family: courier;">const fetchTask = task(() => fetch('https://example.com/data'))</span></p><div>If you call <span style="font-family: courier;">fetchTask()</span>, only then will your HTTP call be executed.</div><h3 style="text-align: left;">Fluture</h3><div>There are also other viable options, like <a href="https://github.com/fluture-js/Fluture" target="_blank">Fluture</a>, which is a Future implementation in Javascript. I'm not aiming to discuss Future-s here, but it might be mentioned, that it is a monadic interface that is lazy by it's nature - in a way it's similar to Promise, but more functional, with it's advantages.</div>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-29549872011399011402023-03-05T00:20:00.001-08:002023-03-05T00:20:03.307-08:00OPENAPI discriminators<p> OpenAPI discriminators are a feature of the OpenAPI Specification (formerly known as Swagger) that allows you to define alternative schemas for different values of a property.</p><p>In other words, you can use a discriminator to specify different schema definitions based on the value of a property. For example, you may have an "animal" schema with a discriminator property called "type". The "type" property could have possible values of "cat" or "dog". You could then define different schema definitions for the "cat" and "dog" types.</p><p>Discriminators are especially useful for modeling inheritance in your API schema. By using discriminators, you can define common properties and behaviors for a group of related schemas, while still allowing for differences in their specific implementations.</p><p>The discriminator property is used to select the appropriate schema definition for a given value. The value of the discriminator property is typically found in the JSON payload of a request or response.</p><p>Let's say we want to define a schema for different types of animals, with common properties like "name" and "age", but with different properties based on the type of animal. We can use a discriminator to define alternative schemas based on the value of the "type" property:</p><p><span style="font-family: courier;">components:</span></p><p><span style="font-family: courier;"> schemas:</span></p><p><span style="font-family: courier;"> Animal:</span></p><p><span style="font-family: courier;"> type: object</span></p><p><span style="font-family: courier;"> properties:</span></p><p><span style="font-family: courier;"> name:</span></p><p><span style="font-family: courier;"> type: string</span></p><p><span style="font-family: courier;"> age:</span></p><p><span style="font-family: courier;"> type: integer</span></p><p><span style="font-family: courier;"> discriminator:</span></p><p><span style="font-family: courier;"> propertyName: type</span></p><p><span style="font-family: courier;"> required:</span></p><p><span style="font-family: courier;"> - type</span></p><p><span style="font-family: courier;"> </span></p><p><span style="font-family: courier;"> Dog:</span></p><p><span style="font-family: courier;"> allOf:</span></p><p><span style="font-family: courier;"> - $ref: '#/components/schemas/Animal'</span></p><p><span style="font-family: courier;"> - type: object</span></p><p><span style="font-family: courier;"> properties:</span></p><p><span style="font-family: courier;"> breed:</span></p><p><span style="font-family: courier;"> type: string</span></p><p><span style="font-family: courier;"> </span></p><p><span style="font-family: courier;"> Cat:</span></p><p><span style="font-family: courier;"> allOf:</span></p><p><span style="font-family: courier;"> - $ref: '#/components/schemas/Animal'</span></p><p><span style="font-family: courier;"> - type: object</span></p><p><span style="font-family: courier;"> properties:</span></p><p><span style="font-family: courier;"> color:</span></p><p><span style="font-family: courier;"> type: string</span></p><div><div>In this example, we define a base schema called "Animal" with properties for "name" and "age", and a discriminator called "type" that will be used to select the appropriate schema for each animal. We also define two alternative schemas called "Dog" and "Cat", which extend the "Animal" schema with additional properties specific to dogs and cats.</div><div>If a request or response payload includes an animal with a "type" property of "dog", the schema definition for "Dog" will be used. Similarly, if the "type" property is "cat", the "Cat" schema will be used.</div><div>Here's an example payload for a dog:</div></div><div><div><span style="font-family: courier;">{</span></div><div><span style="font-family: courier;"> "type": "dog",</span></div><div><span style="font-family: courier;"> "name": "Fido",</span></div><div><span style="font-family: courier;"> "age": 3,</span></div><div><span style="font-family: courier;"> "breed": "Golden Retriever"</span></div><div><span style="font-family: courier;">}</span></div></div><div><span style="font-family: inherit;">And here's an example payload for a cat:</span></div><div><div><span style="font-family: courier;">{</span></div><div><span style="font-family: courier;"> "type": "cat",</span></div><div><span style="font-family: courier;"> "name": "Whiskers",</span></div><div><span style="font-family: courier;"> "age": 2,</span></div><div><span style="font-family: courier;"> "color": "tabby"</span></div><div><span style="font-family: courier;">}</span></div><div><br /></div><div>In this way, discriminators allow you to define flexible, extensible API schemas that can adapt to a variety of use cases.</div></div>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-9450788448733623272023-03-05T00:16:00.003-08:002023-03-05T00:16:30.153-08:00AsyncGenerator<p>In TypeScript, an <span style="font-family: courier;">AsyncGenerator</span> is a special type of generator function that can be used to asynchronously generate a sequence of values.</p>
<p>Like a regular generator function, an <span style="font-family: courier;">AsyncGenerator</span> is defined using the <span style="font-family: courier;">function*</span> syntax, but with the addition of the async keyword before the function keyword:</p>
<div><span style="font-family: courier;">async function* myAsyncGenerator() {</span><span style="font-family: courier;"> // ...</span><span style="font-family: courier;">}</span></div>
<p><span style="font-family: inherit;">An </span><span style="font-family: courier;">AsyncGenerator</span><span style="font-family: inherit;"> function can use the </span><span style="font-family: courier;">yield</span><span style="font-family: inherit;"> keyword to return values one at a time, just like a regular generator. However, because it is an asynchronous function, it can also use the </span><span style="font-family: courier;">await</span><span style="font-family: inherit;"> keyword to pause execution until an asynchronous operation completes before continuing to the next </span><span style="font-family: courier;">yield</span><span style="font-family: inherit;"> statement.</span></p>
<p></p>
<p><span style="font-family: inherit;">Here is an example of an AsyncGenerator that asynchronously generates a sequence of random numbers:</span></p>
<div><span style="font-family: courier;">async function* randomNumbers(count: number): AsyncGenerator<number> {</span><span style="font-family: courier;"> for (let i = 0; i < count; i++) {</span><span style="font-family: courier;"> // Wait for a random number to be generated asynchronously</span><span style="font-family: courier;"> await new Promise(resolve => setTimeout(resolve, 1000));</span><span style="font-family: courier;"> }</span><span style="font-family: courier;">}</span></div>
<div><br /></div><div>To use an <span style="font-family: courier;">AsyncGenerator</span>, you can call it like a regular generator and iterate over the values it generates using a <span style="font-family: courier;">for-await-of</span> loop:</div><div><br /></div>
<div>
<div><span style="font-family: courier;">async function printRandomNumbers(count: number) {</span></div>
<div><span style="font-family: courier;"> for await (const number of randomNumbers(count)) {</span></div>
<div><span style="font-family: courier;"> console.log(number);</span></div>
<div><span style="font-family: courier;"> }</span></div>
<div><span style="font-family: courier;">}</span></div>
</div>
<div>This will asynchronously generate and print count random numbers, one per second.</div>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-63541131019191632352023-03-05T00:08:00.002-08:002023-03-05T00:08:48.987-08:00Employee Stock Options<p>Stock option: the opportunity to buy a stock at a set price up until some date in the future.</p><p>So what does this actually mean for an employee? Let's say you are given 100 options for the price 15 USD for 5 years. That would be worth now (if you could sell it) 1500 USD-s. Let's say in five years the stock of the company goes up 5 USD-s, so now it's 20 USD-s. Because you got the options for 15 USD, and now it's worth 20 USD-s, the company practically gives you 5 USD-s (20-15) per options, so you have 100*5 = 500 USD profit!</p><p>Vesting refers to the process by which an employee earns ownership of an asset, such as stock options, over time. In the context of employee stock options, vesting typically means that an employee gains the right to exercise (i.e., purchase) a certain number of shares of their company's stock at a set price (known as the "strike price") over a predetermined period of time, known as the "vesting period."</p><p>The vesting period is usually several years long and is intended to incentivize employees to stay with the company and contribute to its success over the long term. As the employee meets certain milestones or stays with the company for a certain length of time, they earn the right to exercise more of their stock options. Once the options have vested, the employee has the choice to exercise them, usually by paying the strike price, and can then sell the shares on the open market or hold onto them.</p><p>Employee stock options are a common form of equity compensation used by companies to attract and retain talented employees. They are typically offered to employees at all levels of the organization, from executives to rank-and-file workers. The number of options granted and the terms of the vesting schedule vary from company to company and can depend on factors such as the employee's role, tenure, and performance. The hope is that by providing employees with a financial stake in the company's success, they will be more motivated to work hard and help the company achieve its goals.</p>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-32525487889209713362023-03-04T23:41:00.003-08:002023-03-04T23:48:59.357-08:00PromQL (Prometheus Query Language) notes<p><a href="https://prometheus.io/docs/prometheus/latest/querying/basics/" target="_blank">PromQL (Prometheus Query Language)</a> is a query language used to retrieve and manipulate time series data stored in Prometheus. Mos important aspects of PromQL:</p><p></p><ul style="text-align: left;"><li>Selecting metrics: You can select metrics by their name or by using regular expressions. For example, <span style="font-family: courier;">up</span> selects all metrics with the name <span style="font-family: courier;">up</span>, while <span style="font-family: courier;">node_cpu.*</span> selects all metrics with names starting with <span style="font-family: courier;">node_cpu</span>.</li><li>Filtering metrics: You can filter metrics by their labels using curly braces <span style="font-family: courier;">{}</span>. For example, <span style="font-family: courier;">up{job="prometheus"}</span> selects all metrics with the name <span style="font-family: courier;">up</span> and the label <span style="font-family: courier;">job</span> equal to <span style="font-family: courier;">prometheus</span>.</li><li>Aggregating data: PromQL provides a variety of functions to aggregate time series data. For example, <span style="font-family: courier;">sum()</span> calculates the sum of values across multiple time series, while <span style="font-family: courier;">avg()</span> calculates the average value across multiple time series.</li><li>Grouping data: You can group data by one or more labels using the <span style="font-family: courier;">by</span> keyword. For example, <span style="font-family: courier;">sum(rate(http_requests_total{method="GET"}[5m])) by (status_code)</span> groups the data by the <span style="font-family: courier;">status_code</span> label.</li><li>Working with time: PromQL supports a variety of time-related functions, such as <span style="font-family: courier;">time()</span> to get the current timestamp, <span style="font-family: courier;">offset()</span> to shift the data by a certain time interval, and <span style="font-family: courier;">rate()</span> to calculate the rate of change over a time period.</li></ul><p></p><p>PromQL provides a powerful and flexible way to analyze and query time series data stored in Prometheus.</p>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-54372092679755877252023-03-04T23:37:00.002-08:002023-03-04T23:38:23.745-08:00Consistent hashing via hash ring<p> Consistent hashing via hash ring is a technique used in distributed computing systems to evenly distribute data and workload across a group of servers, while also minimizing the impact of server failures and additions on the system.</p><p>In this technique, servers are arranged in a circular ring, with each server represented by a point on the ring. The ring is typically implemented using a hash function that maps keys to points on the ring. The keys in this context refer to the data or workload that needs to be distributed across the servers.</p><p></p><div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEh94ewNcLawEs11UzGHNJvqgFkuFMK8e-C46SCNa8awCmrMysNcaFwTAI1-zRmRVrNpNsM2J4-MLCEYhSoDRl76pP_Ve14F2LoPPCMnNwEUtXHQpQEkJqXH1M7N6KtXLDQw0gc6VwwDQvspRsgSnaczQPNNMKbTObanBm6jLRmqjxcVlH7IVNnxmoQA" style="margin-left: auto; margin-right: auto;"><img alt="" data-original-height="690" data-original-width="684" height="240" src="https://blogger.googleusercontent.com/img/a/AVvXsEh94ewNcLawEs11UzGHNJvqgFkuFMK8e-C46SCNa8awCmrMysNcaFwTAI1-zRmRVrNpNsM2J4-MLCEYhSoDRl76pP_Ve14F2LoPPCMnNwEUtXHQpQEkJqXH1M7N6KtXLDQw0gc6VwwDQvspRsgSnaczQPNNMKbTObanBm6jLRmqjxcVlH7IVNnxmoQA" width="238" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><span style="text-align: left;">Source: <a href="https://medium.com/swlh/consistent-hashing-68c13951083e">https://medium.com/swlh/consistent-hashing-68c13951083e</a></span></td></tr></tbody></table></div><p></p><p>To assign a key to a server, the hash function is applied to the key to obtain its corresponding point on the ring. The server whose point on the ring is the next highest to the key's point is then responsible for handling that key. If a server fails or is added to the system, only the keys that were previously assigned to that server need to be reassigned to a new server. The other keys remain with their previously assigned server.</p><p>By using this technique, the system can achieve good load balancing, as each server is responsible for handling an approximately equal portion of the keys on the ring. Additionally, the impact of server failures and additions is minimized, as only a small portion of the keys need to be reassigned when a server is added or removed.</p><p>Overall, consistent hashing via hash ring is a powerful technique for distributing workload and data in distributed systems, and has been widely used in many large-scale systems, such as content delivery networks and distributed databases.</p>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-83926152946436869972023-03-04T23:33:00.006-08:002023-03-04T23:43:24.380-08:00Backend system design interview notes<p> </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhFElUeYJPutG3gOuo5UNtuyej9qfBYuEtwtsjJYy6odagYewrJs8A-xuivb5UkbhqCJXiwJi7-J5k9DWyqUX3D-XhQeYfQ_e32B9fdLO7XOih5OlFa8hZMVt6YFXhcEC4aME9tydx6LJH1PQHfNAE5c94tqaQc0I--FKKM3vnYoldT_FEXplggN2lQ" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="1476" data-original-width="1954" height="302" src="https://blogger.googleusercontent.com/img/a/AVvXsEhFElUeYJPutG3gOuo5UNtuyej9qfBYuEtwtsjJYy6odagYewrJs8A-xuivb5UkbhqCJXiwJi7-J5k9DWyqUX3D-XhQeYfQ_e32B9fdLO7XOih5OlFa8hZMVt6YFXhcEC4aME9tydx6LJH1PQHfNAE5c94tqaQc0I--FKKM3vnYoldT_FEXplggN2lQ=w400-h302" width="400" /></a></div><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhvavYwnMcmGx358dZ7q6yZjWXDXrhcZ7ziXQby7eCGw1IiI9yL8L4seUdAjDzAI_9fuCuXZ2xlujbSZq5_iHKZYgii-EPPzMIz7BvvyhdkyY4qWwBNI9H6FkFicAKCJsieIHsLQn1XGLeTpCrDdtEQmPgdsLfwQtuKX2hiyD72H4_3JVA9pkDoibhS" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="826" data-original-width="1532" height="216" src="https://blogger.googleusercontent.com/img/a/AVvXsEhvavYwnMcmGx358dZ7q6yZjWXDXrhcZ7ziXQby7eCGw1IiI9yL8L4seUdAjDzAI_9fuCuXZ2xlujbSZq5_iHKZYgii-EPPzMIz7BvvyhdkyY4qWwBNI9H6FkFicAKCJsieIHsLQn1XGLeTpCrDdtEQmPgdsLfwQtuKX2hiyD72H4_3JVA9pkDoibhS=w400-h216" width="400" /></a></div><br /><br /><p></p><p></p><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijyqU__CT0nMZDOMmybBBVkeJNTwa888Ex9OQMUieyEWyG2pTwTWr5lTAsEz0vUbf3cJiyssxUi7W9G_aDPqoI6P3Hav-RtHloHnKpN3DNzTy-ECc8z_dsGULtwEDEMUwgntBiI8g8YReBPugS3-9si1_Qu6ZWeKjIwaS4Bo_tRpD6pDEmUKCz7r2t/s750/pedals-final.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="750" height="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijyqU__CT0nMZDOMmybBBVkeJNTwa888Ex9OQMUieyEWyG2pTwTWr5lTAsEz0vUbf3cJiyssxUi7W9G_aDPqoI6P3Hav-RtHloHnKpN3DNzTy-ECc8z_dsGULtwEDEMUwgntBiI8g8YReBPugS3-9si1_Qu6ZWeKjIwaS4Bo_tRpD6pDEmUKCz7r2t/s320/pedals-final.png" width="320" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><br /></div><br /><br /></div><br /><br /><p></p><div>Good resource: <a href="https://prometheus.io/docs/prometheus/latest/querying/basics/" target="_blank">https://interviewing.io/guides/system-design-interview </a></div><p></p>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-82581479367654049392022-12-11T22:31:00.005-08:002022-12-11T22:39:27.389-08:00Frontend system design interview notes<p>First of all, _make sure you understand the whole picture_. This means you need to ask _many_ questions before jumping on actually hatching out a plan.</p><p>Also very important note is that 99% of the time any solution will have PRO-s _and_ CON-s. This is very important from a designing perspective as (the more senior the role is) we will need to weigh in both sides.</p><p>Here is a pretty good mock interview: <a href="https://www.youtube.com/watch?v=VM2_4IXkMZ0">https://www.youtube.com/watch?v=VM2_4IXkMZ0</a></p><p>Also from the same author here is a textual version of the above video: <a href="https://www.feinfra.com/">https://www.feinfra.com/</a> </p><p>Questions about the product:</p><p></p><ul style="text-align: left;"><li>liveness of the data</li><ul><li>REST</li><li>websockets</li></ul><li>who is the audience (users)</li><ul><li>how well educated are they in terms of the app</li><li>will the product allow users's users (kinda admin)</li></ul><li>what kind of team do we already have? are they already familiar with e.g. React?</li><li>how long is the project plan? (6 months? 2 years?)</li><li>what kind of user audience size do we expect? should we worry about scaling our product at this stage?</li></ul><p></p><p>Important topics</p><p></p><ul style="text-align: left;"><li>bare minimum html/js vs Next.JS SSR vs SPA</li><li>CI/CD</li><li>testing</li><ul><li>unit (jest)</li><li>e2e (cypress)</li><li><a href="https://www.datadoghq.com/knowledge-center/synthetic-testing/" target="_blank">synthetic</a></li></ul><li>optimization</li><ul><li>minifying css/js</li><li>optimize media assets</li></ul><li>monitoring</li><ul><li>DataDog / Sentry / Google Analytics / ...</li></ul><li>security</li><ul><li>XSS, CSRF, SQL injection, ...</li></ul><li>A/B testing</li><li>CDN</li><ul><li>Content Delivery Network (I keep forgetting this name..)</li></ul><li>code infrastructure setup</li><ul><li>monorepo / multiple repos</li><li>shared UI component library</li><li>service-oriented architecture: teams focusing on each part of the domain, pro-s / con-s</li></ul><li>related to the previous point: do we have a design system already?</li><ul><li>css framework like tailwind?</li></ul><li>sharing types between FE and BE</li><li>API contracts</li><ul><li>OpenAPI, GraphQL, etc..</li><li>ProtoBuff - code generation like React hooks (wow)</li></ul><li>state management</li><ul><li>React Context</li><li>zustand / jotai / Redux / ...</li></ul><li>router</li><ul><li>react router e.g.</li></ul><li>do we have OKR-s set?</li><li>SLA-s</li><ul><li>contenful paint</li></ul><li>(Google's) Core Web Vitals</li><ul><li><a href="https://blogger.googleusercontent.com/img/a/AVvXsEikRh3RDV6imdxIpKKsFvr38F81EuPz-zVIFVJId_UwEWKgPoXzGe96elpyyjr0WLyyVAwpT-RZVk-pgEKSdxcngz4V-eanMj2ty92Cj8t-vC_GJNQWGI8IxJjWWcK6UdZNZ3hoA4FQu7jVDSnPqZKZuXsr02sXJFLb8vTAqnEOzhYl0Klbrajam2Il" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="388" data-original-width="1000" height="155" src="https://blogger.googleusercontent.com/img/a/AVvXsEikRh3RDV6imdxIpKKsFvr38F81EuPz-zVIFVJId_UwEWKgPoXzGe96elpyyjr0WLyyVAwpT-RZVk-pgEKSdxcngz4V-eanMj2ty92Cj8t-vC_GJNQWGI8IxJjWWcK6UdZNZ3hoA4FQu7jVDSnPqZKZuXsr02sXJFLb8vTAqnEOzhYl0Klbrajam2Il=w400-h155" width="400" /></a> (<a href="https://www.hostinger.com/tutorials/core-web-vitals#What_Are_Core_Web_Vitals" target="_blank">source</a>)</li><li>The Largest Contentful Paint (LCP) checks the render time of a page’s main content when it starts loading. The main content is generally the largest image or a text block in the viewport – a visible area of a web page on a user’s device.</li><li>The First Input Delay (FID) measures input latency – how long it takes for a site to respond to a user’s input. This includes key presses, taps, and clicks on buttons, links, and videos or audios on a page.</li><li>The Cumulative Layout Shift (CLS) measures visual stability and checks whether there is an unexpected layout shift in the page.</li></ul><li>wireframing?</li><li>styling guidelines</li><ul><li>styled components</li><li>css modules</li></ul></ul><p></p>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-25779899831321304422022-12-05T22:46:00.003-08:002022-12-05T22:46:57.208-08:00JS can surprise me still to this day (Array toString() is join())<p>I didn't know but these expressions yield the same result in JavaScript:</p><p><span style="font-family: courier;">const a = [1,2,3];</span></p><p><span style="font-family: courier;">console.log(a.join(','));</span></p><p><span style="font-family: courier;">console.log(`${a}`);</span></p><p>I think it makes sense, but still, the language still today can surprise me.</p>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-198264049473529192022-09-15T23:51:00.002-07:002022-09-15T23:51:48.294-07:00Jest test array with objects without order<p>Hello internet!</p><p>As I was doing my regular weekday I met a surprisingly unsolved problem in Jest, namely what if I wanted to test an array's _content without order_?</p><p>So e.g. these 2 arrays should equal</p><p><span style="font-family: courier;">[{cat: 'Takira'}, {cat: 'Inari'}]</span></p><p>and</p><p><span style="font-family: courier;">[{cat: 'Inari'}, {cat: 'Takira'}]</span>.</p><p>There is an <a href="https://stackoverflow.com/questions/32103252/expect-arrays-to-be-equal-ignoring-order" target="_blank">SO</a> post about this, but it doesn't care about objects, but only primitives. Also it points to Jasmine (which does have this as a native feature), but not Jest.</p><p>So here is my generic solution to the problem</p><p><span style="font-family: courier;">for (obj in array) {</span></p><p><span style="font-family: courier;"> expect(obj).toEqual(</span></p><p><span style="font-family: courier;"> expect.arrayContaining([</span></p><p><span style="font-family: courier;"> expect.objectContaining(obj)</span></p><p><span style="font-family: courier;"> ])</span></p><p><span style="font-family: courier;"> );</span></p><p><span style="font-family: courier;">}</span></p><p>Let's go through this step by step!</p><p>So we are looping through the array (so far so good) and then we simply expect that object to be in the array.</p><p>That's literally it.</p><p>Thank You For Coming to My TED Talk.</p>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-30437564923654869882022-09-11T00:00:00.001-07:002022-09-11T00:00:06.653-07:00A painful lesson I learned while putting out fire<p>Imagine you have a service that's unresponsive, yet you can see in your production environment it yields 500-s for every request. SLO-s are fine, no alert is being invoked, everything seems to be normal.</p><p>What do you do?</p><p>At first, I didn't know what to do, but after the first shock I had the - not that imaginative - idea to restart the service. For our production evnironment we use <a href="https://github.com/shipitjs/shipit" target="_blank">shipit</a> as a helper for these kind of situations. As a long time software engineer I am familiar with a lot of tool, but this was the first time looking at the shipit user interface. So I went back to my roots where we restarted services by a new deployment. That was arguably not the best decision I admit, yet there I was trying to put out fire. The new deployment went through! Everything should be back up again and running smooth like a sailboat! Right. Right? Right??</p><p>Well, this should've been the case, but when I went back to check on the service, it showed still the same error. Bummer.</p><p>What to do now?</p><p>Let's check logs.</p><p>OK, logs show practically nothing. I mean, nothing for the past 10 minutes.</p><p>That's not good.</p><p>How will I know what's happening inside the container?</p><p>OK, calm down. This is a great challenge that you can solve. Embrace it.</p><p>Cool, let's have a look what was the last thing the container logged!</p><p>Maximum call stack size exceeded.</p><p>That's not good. What could possibly cause that so badly that the service stops reporting?</p><p>Let's check the stacktrace.</p><p>Something-something.. loggerInstace .. something-something.. winston..</p><p>Ok, so something's wrong with logging? </p><p>Ouch.</p><p>So we don't know anything about the inner parts of the service, because the _logging_ has issues.</p><p>In the meantime I tried to redeploy again, same result - 500-s after the deployment.</p><p>This is not looking good.</p><p>BUT! Teammates are there for you when you them the most! <a href="https://github.com/indarian" target="_blank">Sergei</a> taught me that Shipit has a "restart" feature!</p><p>OK, let's do that.</p><p>It works.</p><p>WHAT.</p><p>Damn.</p><p>So when we deployed shipit didn't actually do any changes? Weird.</p><p>Let's check the kubernetes pods.</p><p>They are old. They definitely didn't restart when I redeployed.</p><span><a name='more'></a></span><p><b><i>TLDR;</i></b></p><p>Shipit has a "restart application" command that can be used to restart your application (isn't that weird?). This can solve your production issues when having OOM, and the redeployment might not do the trick.</p><p>Disclaimer: this might be just current project specific, as shipit can be customized heavily, nevertheless this was a good learning, that redeployment of the same commit might not do the same thing as a restart of the application.</p>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-54975390626300019032022-02-12T01:34:00.000-08:002022-02-12T01:34:00.916-08:00Cancellable Promises<p> Have you ever been in a situation where React tried to update a component that <a href="https://stackoverflow.com/questions/53949393/cant-perform-a-react-state-update-on-an-unmounted-component" target="_blank">has been already unmounted</a>?</p><p>This can be easily witnessed when your business logic is relying on some asynchronous code that would update the state once a promise resolved.</p><p>How can we prevent that from happening?</p><p>Meet <span style="font-family: courier;">cancellable</span>.</p><p><br />
<script src="https://gist.github.com/nagyadam2092/bb72e894058680fc591b1c1eadf425d4.js"></script>
</p><p>So why is this so cool? And how can I use this?</p><p>Do you remember that <span style="font-family: courier;">useEffect</span> has a <a href="https://reactjs.org/docs/hooks-effect.html#example-using-hooks-1" target="_blank">cleanup method</a>? That's the function that's returned inside the <span style="font-family: courier;">useEffect</span>'s callback method. You can take care of situations when components are unmounted e.g.</p><p>Sounds familiar? That's the problem we started with!</p><p>So basically, if you return a <span style="font-family: courier;">cancellable</span> inside a <span style="font-family: courier;">useEffect</span>, it takes care automatically of the cleanup as it's gonna set the <span style="font-family: courier;">cancelled</span> variable, and later when trying to do some state updates, our logic will prevent that because of this peace of code: <span style="font-family: courier;">.then((v) => cancelled || ok(v))</span>. <span style="font-family: courier;">cancelled</span> will prevent from calling the <span style="font-family: courier;">ok</span> method (in our case it could be a setState).</p><p>And that's it! Now you have a neat little function that is taking care of Promises that are still unfinished by the time the component has already been unmounted!</p>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-40915755749840207982021-11-09T23:49:00.001-08:002021-11-09T23:49:48.666-08:00How to find the actual differences of 2 Objects in JS<p> The title says it all, here is the solution I fall back to most of the times.</p><p>https://stackoverflow.com/a/8596559</p><p><br /></p><br />
<script src="https://gist.github.com/nagyadam2092/8eff43c9afc97e3292248ff60f1bf019.js"></script>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-74138085737510932362021-04-21T00:29:00.004-07:002021-04-21T00:32:16.435-07:00Why do we need Monads?<div class="preview__inner-2"><div class="cl-preview-section"><ol><li><p>We want to program <strong>only using functions</strong>. (“functional programming” after all -FP).</p>
</li>
<li>
<p>Then, we have a first big problem. This is a program:</p>
<p><code>f(x) = 2 * x</code></p>
<p><code>g(x,y) = x / y</code></p>
</li>
</ol>
</div><div class="cl-preview-section"><p>How can we say <strong>what is to be executed first</strong>? How can we form an ordered sequence of functions (i.e. <strong>a program</strong>) using no more than functions?</p>
</div><div class="cl-preview-section"><p>Solution: <strong>compose functions</strong>. If you want first <code>g</code> and then <code>f</code>, just write <code>f(g(x,y))</code>. OK, but …</p>
</div><div class="cl-preview-section"><ol start="3">
<li>More problems: some functions <strong>might fail</strong> (i.e. <code>g(2,0)</code>, divide by 0). We have <strong>no “exceptions” in FP</strong>. How do we solve it?</li>
</ol>
</div><div class="cl-preview-section"><p>Solution: Let’s <strong>allow functions to return two kind of things</strong>: instead of having <code>g : Real,Real -> Real</code> (function from two reals into a real), let’s allow <code>g : Real,Real -> Real | Nothing</code> (function from two reals into (real or nothing)).</p>
</div><div class="cl-preview-section"><ol start="4">
<li>But functions should (to be simpler) return only <strong>one thing</strong>.</li>
</ol>
</div><div class="cl-preview-section"><p>Solution: let’s create a new type of data to be returned, a “<strong>boxing type</strong>” that encloses maybe a real or be simply nothing. Hence, we can have <code>g : Real,Real -> Maybe Real</code>. OK, but …</p>
</div><div class="cl-preview-section"><ol start="5">
<li>What happens now to <code>f(g(x,y))</code>? <code>f</code> is not ready to consume a <code>Maybe Real</code>. And, we don’t want to change every function we could connect with <code>g</code> to consume a <code>Maybe Real</code>.</li>
</ol>
</div><div class="cl-preview-section"><p>Solution: let’s <strong>have a special function to “connect”/“compose”/“link” functions</strong>. That way, we can, behind the scenes, adapt the output of one function to feed the following one.</p>
</div><div class="cl-preview-section"><p>In our case: <code>g >>= f</code> (connect/compose <code>g</code> to <code>f</code>). We want <code>>>=</code> to get <code>g</code>'s output, inspect it and, in case it is <code>Nothing</code> just don’t call <code>f</code> and return <code>Nothing</code>; or on the contrary, extract the boxed <code>Real</code> and feed <code>f</code> with it. (This algorithm is just the implementation of <code>>>=</code> for the <code>Maybe</code> type).</p>
</div><div class="cl-preview-section"><ol start="6">
<li>
<p>Many other problems arise which can be solved using this same pattern: 1. Use a “box” to codify/store different meanings/values, and have functions like <code>g</code> that return those “boxed values”. 2. Have composers/linkers <code>g >>= f</code> to help connecting <code>g</code>'s output to <code>f</code>'s input, so we don’t have to change <code>f</code> at all.</p>
</li>
<li>
<p>Remarkable problems that can be solved using this technique are:</p>
<ul>
<li>
<p>having a global state that every function in the sequence of functions (“the program”) can share: solution <code>StateMonad</code>.</p>
</li>
<li>
<p>We don’t like “impure functions”: functions that yield <em>different</em> output for <em>same</em> input. Therefore, let’s mark those functions, making them to return a tagged/boxed value: <code>IO</code> monad.</p>
</li>
</ul>
</li>
</ol>
</div><div class="cl-preview-section"><p>PS: this answer can be found on SO at this link: <a href="https://stackoverflow.com/a/28135478" target="_blank" rel="nofollow">https://stackoverflow.com/a/28135478</a> </p>
</div></div>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-63643977829431916362021-04-16T00:46:00.003-07:002021-04-16T00:46:34.648-07:00Do you need to wrap RXJS Observables in try-catch?<p> No.</p><p>Internally errors are caught implicitly.</p><p>Here is a good example, give it a swing yourself! (<a href="https://stackoverflow.com/questions/53566599/how-does-rxjs-catch-errors-under-the-hood" rel="nofollow" target="_blank">Source</a>)</p><p><br /></p><p>
<script src="https://gist.github.com/nagyadam2092/346ea7a60ee11ea345afb907cda99fb2.js"></script></p>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0tag:blogger.com,1999:blog-1762524982174490639.post-45354282283537621282021-04-10T00:05:00.003-07:002021-04-10T00:05:24.666-07:00Conditional Promise.all<p>Have been in a situation where you needed to <i>dynamically</i> shoot out HTTP requests based on some branching logic? Are you using a Promise based HTTP client library like fetch or axios?</p><p>Fear not, here is a solution for your needs!</p><p>In general the solution is based on coming up with an interface that's not only returning the data when the Promise was resolved, but also give a companion flag that identifies the promise it was initiated from.</p><p><br /></p>
<p><script src="https://gist.github.com/nagyadam2092/6bd214f3a17edb389da9975d066a6d12.js"></script></p>
<p>You can find the idea on <a href="https://stackoverflow.com/questions/47524790/conditional-dynamic-array-promise-all" rel="nofollow" target="_blank">this SO post</a> as well.</p>Adam Nagyhttp://www.blogger.com/profile/03531901890912524639noreply@blogger.com0