14 Temmuz 2021 Çarşamba

GraphQL Mutation - CRUD İşlemleridir

Giriş
POST isteği ile gönderilir. JSON döner. Mutation ile create, update, delete işlemleri yapılır. Mutation bir sonuç dönebilir.
Metodun içine gönderilecek parametreler yazılır, döndürülecek sonuçlar ise süslü parantez içindedir.
Örnek
Şöyle yaparız. Burada name ve country değerleri gönderiliyor. Sonuç olarak yine aynı parametreler isteniyor.
mutation {
  createAuthor(name: 'Brandon Sanderson', country: "USA") {
    name
    country
  }
}
Eğer yeni bir kayıt yaratsaydık ve sonuç olarak id isteseydik şöyle yaparız
mutation {
  createAuthor(name: 'Brandon Sanderson', country: "USA") {
    id
  }
}

Örnek
Şöyle yaparız
mutation {
  project_tracker {
    createTicket(title : "New ticket", author_id : 11824) {
      id
    }
  }
}
Açıklaması şöyle
In our example, the createTicket mutation accepts two arguments for creating a ticket: title and author_id. On ticket creation, we return the $id of the newly created ticket. Just like the query, the mutation is a root object type. Mutations, for the most part, are very flexible and can return whatever you desire: scalars such as int, string, bool, and core types like the Ticket, or even custom response objects. Similar to queries, if the mutation field returns an object type, you can ask for nested fields. 
Örnek
Şöyle yaparız
type Author {
  id: ID!
  firstName: String!
  lastName: String!
}

type Query {
  findAllAuthors: [Author]!
  countAuthors: Long!
}

type Mutation {
  newAuthor(firstName: String!, lastName: String!) : Author!
}

13 Temmuz 2021 Salı

Load Balancer

Giriş
Load balancer ayrı bir cihazdır. Yükü dağıtacağı sunucuların listesini bilir. Bir sunucu bakım veya arıza için kapatılırsa load balancer listesinden silinir.

Load Balancer tarafından kullanılacak algoritma tamamen kendi çözmek istediğimiz problem ile ilgili olabilir. Örneğin Load Balancer müşteriyi kendisine en yakın sunucuya yönlendirme algoritması kullanabilir. Bir örnek şöyle
Load Balancer: It is used to divide the traffic, i.e., to balance the load on basis of some algorithms or some strategy defined by us.

We can define the strategy, the person who lives nearest to the particular shop should go to that shop.
L4 vs L7 Load Balancer
Açıklaması şöyle
L4 : Makes balancing decision only on IP address , tcp port. Cannot see request header, client, type etc.
L7 : Has info about url, message, request type, header, client everything. Can route request based on type of request

Use L4 when you need to make simple reliable and fast balancing decision on server load, which has reliable TCP connection. Use L7 when you need to route request to appropriate resource server, such as image request will go to image server etc.
HAProxy
HAProxy yazısına taşıdım

Load Balancer Algoritmaları
4 tanesi şöyle
1. Random Algorithm
2. Round-Robin Algorithm
3. Weighted Round-Robin
4. Hash Algorithm

2 Temmuz 2021 Cuma

RabbitMQ Kurulum

Giriş
Windows'a kurulum için bir yazı burada. RabbitMQ Erlang ile çalıştığı için önce Erlang kurulumu yapmak gerekir.

Docker
İki tane image var
1. rabbitmq:3-management : Bu image ile management plugin etkin geliyor
2. rabbitmq

Örnek - docker
Şöyle yaparız. 1562 portu "http://localhost:15672/" yani dashboard için gerekir.
docker run -d --hostname my-rabbit --name rabbitmq-dlx
-p 15672:15672 -p 5672:5672 rabbitmq:3-management
Örnek
Şöyle yaparız
docker run -d --name some-rabbit 
  -p 4369:4369 
  -p 5671:5671 
  -p 5672:5672 
  -p 15672:15672 
  rabbitmq

# Enable management plugin
docker container exec -it some-rabbit 
  rabbitmq-plugins enable rabbitmq_management

Örnek - Docker
docker-compose.yml dosyasına şöyle yazarız
version: '3.7'
services:
  avc-rabbit:
    image: rabbitmq:3-management
    container_name: rabbitmq
    ports:
      - "15672:15672"
      - "5672:5672"
Çalıştırmak için şöyle yaparız
docker-compose up -d
Örnek - Komut Satırı
Şöyle yaparız
cd C:\Program Files\RabbitMQ Server\rabbitmq_server-3.7.7\sbin

rabbitmq-server.bat start
Web Management Console
C:\Program Files\RabbitMQ Server\rabbitmq_server-X\sbin\ altındaki şu komut çalıştırılır. Böylece artık management console'a giriş yapabiliriz.
rabbitmq-plugins.bat enable rabbitmq_management
Açıklaması şöylehttp://localhost:15672 adresine guest:guest olarak bağlanabiliyoruz.
15672 exposes a web management page that you can check out by opening a browser, navigating to http://localhost:15672, and using the credentials guest:guest.
Açıklaması şöyle
RabbitMQ has a user-friendly interface that lets you monitor and handle your RabbitMQ server from a web browser. Among other things, queues, connections, channels, exchanges, users and user permissions can be handled (created, deleted, and listed) in the browser, and you can monitor message rates and send/receive messages manually.
Exchanges Sekmesi
Şeklen şöyle. Burada yeni exchange de eklenebilir.


Shovel Plugin
Bu eklenti ile kuyrukta çok fazla bekleyen mesajlar "Dead Letter Exchange" yani ölü mesaj kuyruğuna gönderilebilir.

30 Haziran 2021 Çarşamba

Minimum Spanning Tree

Giriş
Açıklaması şöyle
Find the subtree of the input graph that minimizes the total weight of its edges. 
Prim- Dijkstra algorithm
Açıklaması şöyle
In Dijkstra's original paper, he talks about two problems related to graphs. The second one is the problem of finding the shortest path between two nodes, which is what is most commonly meant by Dijkstra's algorithm. However, he also poses another problem, namely that of constructing the tree of minimum total length between the n nodes of the connected graph.
Açıklaması şöyle
The algorithm here suggested by Dijkstra is today known as Prim's algorithm.
Kruskal's algorithm
Açıklaması şöyle
Kruskal's algorithm works as follows:
- sort the edges by increasing weight
- repeat: pop the cheapest edge, if it does not create cycles, include it in the MST

29 Haziran 2021 Salı

git .gitattributes Dosyası

End Of Line Formatlama Nasıl Olmalı
İki seçenek var
1. .gitattributes dosyasına eklemeler yapmak 
2. git config ile istenilen değeri atamak

Bu iki yöntemden .gitattributes tercih edilmeli 

.gitattributes Dosyası Yöntemi
Not : IntelliJ kullanıyorsak Settings > Editor > Code Style altında Line separator alanı Unix and macOs (\n) seçilmeli. Böylece her şey her zaman Linux gibi olacak

.gitattributes dosyasındaki text değerinin açıklaması şöyle
text
This attribute enables and controls end-of-line normalization. When a text file is normalized, its line endings are converted to LF in the repository. To control what line ending style is used in the working directory, use the eol attribute for a single file and the core.eol configuration variable for all text files.
Örnek - Kod Dosyaları İçin LF'i Muhafaza Etmek
Kısaca şöyle yaparız. Kod için şöyle yaparız
# linux line-endings
*        text eol=lf
Eğer zaten git'e ekli dosyalar varsa ve .gitattributes sonradan ekleniyorsa, .gitattributes dosyasını oluşturduktan sonra dosyayı IntelliJ ile açıp satır sonunu LF yaparız. Bu durumda git dosyada değişiklik olduğunu düşünüyor. Daha sonra şöyle yaparız
git add --renormalize .
Bunu yapınca git artık değişiklik olduğunu düşünmüyor.

Örnek - *.sh Dosyaları İçin LF'i Muhafaza Etmek
Windows bilgisayarda checkout yaparken bash betiklerinin (script) bozulmaması için şöyle yaparız
*.sh text eol=lf
Aynı şey sanırım şöyle de yapılabilir.
# Never modify line endings of our bash scripts
*.sh -crlf
Örnek - Dosya Uzantısına Göre Karışık Kullanım
Şöyle yaparız
# auto
*           text=auto     
*.txt       text

# windows line-endings
*.vcproj    text eol=crlf 

# linux line-endings
*.sh        text eol=lf   

*.jpg       -text
Örnek - auto normalization
Şöyle yaparız
* text=auto
Açıklaması şöyle. Böylece Windows'tan commit yapsak bile repository 'de LF olarak saklanır. Windows checkout yaparken CRLF olarak alır, Linux ise LF olarak alır.
With this set, Windows users will have text files converted from Windows style line endings (\r\n) to Unix style line endings (\n) when they’re added to the repository.

git config Yöntemi
Windows'ta End Of Line formatlamayı Linux gibi için şöyle yaparız
git config --global core.autocrlf true
Linux'ta End Of Line formatlamayı Linux gibi için şöyle yaparız
git config --global core.autocrlf input

28 Haziran 2021 Pazartesi

Software Configuration Management Süreci - Semantic Versioning

Giriş
Açıklaması şöyle
According to semantic versioning, a version number has 03 parts as MAJOR, MINOR and PATCH.

MAJOR version change: Incremented when you make incompatible API changes. Consumers that use the service will be affected.
MINOR version change: when you add functionality in a backwards-compatible manner.
PATCH version change: when you make backwards-compatible bug fixes.
Örnek
Şöyle yaparız
1.2.3
^ ^ ^
| | |
| | +--- Minor bugs, spelling mistakes, etc.
| +----- Minor features, major bug fixes, etc.
+------- Major version, UX changes, file format changes, etc.
MAJOR Version Change
Geriye uyumluluk kırılabilir

MINOR Version Change
Geriye uyumlu yeni API veya bir şey bozmayan yeni REST noktası eklenebilir

PATCH Version Change
Hatalar düzeltilince değiştirilir

Long Term Support
Long Term Support (LTS) doğası gereği hem PATCH Version Change hem de MINOR Version Change içeriyor. 

25 Haziran 2021 Cuma

gRPC SpringBoot Service

Giriş
gRPC servisi SpringBoot içinde de kullanılabilir. grpc-spring-boot-starter kullanılır. Bir örnek burada
1. gRPC Servisi Spring Component olarak tanımlanır
2. Bu service kullanılmak istenilen yerde @GrpcClient anotasyonu ile koda dahil edilir

Örnek
Servisi Spring component yapmak için şöyle yaparız
import io.grpc.stub.StreamObserver;
import org.lognet.springboot.grpc.GRpcService;

@GRpcService
public class UserDetailsService extends
UserDetailsServiceGrpc.UserDetailsServiceImplBase {
...
}
metodları için şöyle yaparız. Burada hem Unary hem de Bi-Directional Stream görülebilir.
@Override
public void generateRandomUser(UserDetailsRequest request,
StreamObserver<UserDetailsResponse> responseObserver) {
  UserDetailsResponse output = UserDetailsResponse.newBuilder()...;
    .setCity(...)
    ...
    .build();
  responseObserver.onNext(output);
  responseObserver.onCompleted();
}

@Override
public StreamObserver<UserDetailsRequest> generateRandomUserStream(
StreamObserver<UserDetailsResponse> responseObserver) {
  return new StreamObserver<UserDetailsRequest>() {
    @Override
    public void onNext(UserDetailsRequest input) {
      UserDetailsResponse output = UserDetailsResponse.newBuilder()
.setCity(...)
        ...
        .build();
responseObserver.onNext(output);
    }
    @Override
    public void onError(Throwable throwable) {
    }
    @Override
    public void onCompleted() {
      responseObserver.onCompleted();
    }
  };
}
Bunu  generateRandomUser() metodunu teker teker çağırmak için şöyle yaparız
import net.devh.boot.grpc.client.inject.GrpcClient;
import reactor.core.publisher.Flux;
@Service
public class UserDetailsGrpcBlockingClient {

  @GrpcClient("UserDetailsService")
  UserDetailsServiceGrpc.UserDetailsServiceBlockingStub userDetailsServiceBlockingStub;

  public Flux<Object> getUserDetailsResponse(Integer range) {
    return
      Flux.range(1, range)
.map(i -> UserDetailsRequest.newBuilder()
                    .setCity(...)
            ...
            .build())
.map(i -> {
  UserDetailsResponse response = this.userDetailsServiceBlockingStub
.generateRandomUser(i);
  return (Object) Map.of(response.getId(), new UserDetails(response));
         })
       .subscribeOn(Schedulers.boundedElastic());
  }
}
stream olarak çağırmak için şöyle yaparız. Burada gRPC StreamObserver nesnesi Flux nesnesine çevriliyor.
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.client.inject.GrpcClient;
import reactor.core.publisher.DirectProcessor;
import reactor.core.publisher.Flux;
import reactor.core.publisher.FluxSink;
import reactor.core.scheduler.Schedulers;

@Service
public class UserDetailsGrpcStreamClient {

  @GrpcClient("UserDetailsService")
  private UserDetailsServiceGrpc.UserDetailsServiceStub stub;

  public Flux<Object> generateUserStreamResponse(Integer range){
    DirectProcessor<Object> processor = DirectProcessor.create();
    StreamObserver<UserDetailsResponse> observer =
new StreamObserverImpl(processor.sink());
    StreamObserver<UserDetailsRequest> inputStreamObserver =
this.stub.generateRandomUserStream(observer);
    return Flux.range(1, range)
      .map(i -> UserDetailsRequest.newBuilder()
        .setCity(...)
        ...
        .build())
      .doOnNext(inputStreamObserver::onNext)
      .zipWith(processor, (a, b) -> b)
      .doOnComplete(inputStreamObserver::onCompleted)
      .subscribeOn(Schedulers.boundedElastic());
  }
}
Çevirmek için şöyle yaparız.
class StreamObserverImpl implements StreamObserver<UserDetailsResponse> {

  final FluxSink<Object> sink;

  public StreamObserverImpl(FluxSink<Object> sink) {
    this.sink = sink;
  }

  @Override
  public void onNext(UserDetailsResponse output) {
  this.sink.next(Map.of(output.getId(), new UserDetails(output)));
  }

  @Override
  public void onError(Throwable throwable) {
    this.sink.error(throwable);
  }

  @Override
  public void onCompleted() {
    this.sink.complete();
  }
}