Race condition on Echo context with GraphQL in Go

Given an API setup with GraphQL and Echo, a colleague ran into a race condition situation. There was a concurrent read/write issue on Echo’s context. GraphQL runs its resolvers in parallel if set so, and when context is shared between resolvers, things can go wrong.

I took a look into Echo’s context implementation and I saw a simple map is used for Get/Set.

For every API call, a handle functions is given an Echo context and executes the GraphQL schema with the specified context.

func handle(c echo.Context) error {
 schema, err := gqlgo.ParseSchema(
  ...
  gqlgo.MaxParallelism(10),
 )

 schema.Exec(
  c,
  ...
 )
}

My solution was to use a custom context which embeds the original one and uses a concurrent map instead of Echo’s. Continue reading Race condition on Echo context with GraphQL in Go

Concurrency in PHP with Swoole

Swoole is a CLI server written in C as a PHP extension. It handles HTTP, TCP and socket servers, offering some really interesting features. The ones I’ve tested and I’m pretty excited about are related to concurrency.

The authors have implemented a concurrency model similar to Go‘s, using coroutines and channels for inter-process communication. It also has a memory map, atomic objects, locks, buffers, timers and others.

I’ve tested their 2.2 version found in PECL, but very recently they’ve release the 4.0.0 version. My enthusiasm suffered a little bit when they’ve introduced a pretty nasty bug with 4.0.0, but they were fast about fixing it, although a new version is not released at the time of writing (but you can compile from master branch).
It’s funny that one day everything was working as expected, and the other day I spent some time until I’ve figured they had just released a new version, and that was causing my issue. I had installed the extension without specifying the version, so a new install got me the latest one.

Below is a very small example of concurrency using routines and a channel. Continue reading Concurrency in PHP with Swoole

Counting number of items in a concurrent map

Lately I’ve been using Go’s concurrent map. And sometimes I needed to count the items I’ve stored in the map. I have ranged over the items and incremented a counter, and it was done:

package main

import (
       "sync"
       "log"
)

func main() {
       m := sync.Map{}
       
       m.Store("k1", "v1")
       m.Store("k2", "v2")
       
       count := 0
       m.Range(func(key, value interface{}) bool{
              count++
              return true
       })

       log.Println(count)
}

But I didn’t want to range over the items each time I wanted to count them. So I thought of incrementing the counter every time an element was added, and to decrementing it when one was removed. The following is just for practice, I didn’t perform any advanced tests. Continue reading Counting number of items in a concurrent map

Go concurrency is elegant and simple

These days I wanted to speed up some data retrieval with Go. Its concurrency model is elegant and simple, it has everything you need built-in.

Let’s say there are some articles that need to be fetched from an API. I have the IDSs of all the articles, and I can fetch them one by one. One request can take even a second, so I added a 1 second sleep to simulate this.

type Article struct {
       ID    uint
       Title string
}

func GetArticle(ID uint) Article {
       time.Sleep(time.Second * 1)
       return Article{ID, fmt.Sprintf("Title %d", ID)}
}

The classic way of doing this is making a request for each article, wait for it to finish, store the data.

var articles []Article
var id uint

for id = 1; id <= 10; id++ {
       log.Println(fmt.Sprintf("Fetching article %d...", id))
       article := GetArticle(id)
       articles = append(articles, article)
}

log.Println(articles)

With a 1 second response time it takes 10 seconds. Now imagine 100 articles or more. Continue reading Go concurrency is elegant and simple