Category Archives: coding

tc

TeamCity : pin and tag a build using the REST API from inside the script

We use Teamcity for most of automation in building/testing/deploying golang microservices to prod and during test phase I wanted to be able to notice easily if an integration/benchmark test crashed a microservice. Pinning the build and tagging it with the word “panic” seemed to be a good idea, from inside the buildconf script :

# txt are are the microservice logfiles, substitute as neeeded
grep panic.go *.txt
retVal=$?
if [ $retVal -eq 0 ]; then
   # grep found panic in some file, tag with panic
   nohup sh -c 'sleep 10 ; curl --header "Origin: https://<your_tc_server>" --header "Authorization: Bearer <yourbearertoken>" --request POST "%teamcity.serverUrl%/app/rest/builds/id:%teamcity.build.id%/tags/" --data panic --header "Content-type: text/plain"' &
   nohup sh -c 'sleep 10 ; curl --header "Origin: https://<your_tc_server>" --header "Authorization: Bearer <yourbearertoken>" --request PUT "%teamcity.serverUrl%/app/rest/builds/id:%teamcity.build.id%/pin/"' &
fi

Took more than expected to figure out this : some examples would be helpful. Note that the build needs to be finished to be able to pin it/tag it so we have to put this ugly sleep to postpone operations on the rest api when the build is finished.

grigna

On the importance of design in software

Many time we face situation were productivity of a software team is impaired by initial flaws in system design. These initial flaws require too much time to be completely removed (the effort of complete rewrite is only marginally touched here and is normally and indication of other problems in your software project )

So, in order for a software team to be able to work at its maximum, good design is a must. Design is much more responsible for productivity than any single coder, scrum master, product manager or development methodology/language in the sense that bad design can take an all-star team using top tools/methodology to perform badly.

There were times when it was taken for granted that before building a system, it was necessary to design it. That time looks gone (even though Agile does not explicitly prohibit making good design). The general idea seems to be that there is “never enough time to do something right, but there’s always enough time to do it over” again.

But what is design in software ?

That kind of intellectual activity which creates a whole from its diverse parts may be called the design of a system

Melvin E. Conway, How Do Committees Invent?

So you compose parts to make the whole system. How you do this ?

It is basically decomposition to generate single parts that acting together will generate the goal. The 2 tools you will need as a designer are :

  • decomposition
  • composition

 But first of all you need :

  • understanding of the system boundaries : the borders of the nation your system lives in
  • understanding the global scenario of what your system is going to do. Designing subsystems without knowing the whole picture is not a good idea.

Why decomposition of a system into smaller components (services) is good for you :

  • information hiding : well identified interfaces create a contract that the component has to provide, hiding any network/system implementation details. This will make the component implementation completely free to be modified/enhanced as long as the new implementation is compliant with the contract.
  • less development time : separate components/services can be developed in parallel since they don’t require (or require little) external dependencies, so less contention between engineers. Every component is independent on integration and performance test that can be developed autonomously.
  • scalability : with little effort in design every component might be deployed in a way to be one of many instances that will make that service scalable when traffic increases.
  • clarity : the system could be studied a component (service) at a time with the result that the whole system could be better designed because it was better understood

We could go on here and analyze what are the criteria to be used in decomposing a system into services. I’ll leave this to another moment and you can find some interesting notes here :

https://blog.acolyer.org/2016/09/05/on-the-criteria-to-be-used-in-decomposing-systems-into-modules/

What I would like to stress is that design is a fundamental phase in software engineering. You can’t just skip it and pretend that since you have a good team you’ll get a good job done.

Thanks to the following for inspiring me on this post :

https://en.wikipedia.org/wiki/Melvin_Conway

https://blog.acolyer.org/2019/12/13/how-do-committees-invent/

https://blog.acolyer.org/2016/09/05/on-the-criteria-to-be-used-in-decomposing-systems-into-modules/

Thanks year 2000 : less is (immensely) more (the 90s produced a lot of crap)

Thanks to god after year 2000 information technology has started moving towards more pragmatic, simple and effective tools and languages. Some examples that in my opinion make this evident : 

Languages and language tools

  • go, rust, swift are all born with the goal of simplifying their direct parents (c++, objectiveC) and removing their pitfalls.
  • UML abandoned : this is a relief for all coders which had to deal with it. I don’t know anyone using it nowadays.
  • git : finally some one (thanks Linux Torvalds) simplified svn/sourcesafe by putting features that are needed by developers in a clear, pretty intuitive command line interface
  • atom/sublime : reaction to the complexity of Visual Studio, IBM Rational, Eclipse ? I think yes

Databases

  • Key-value stores/noSQL are just taking ER/SQL model and making it simpler, providing only the features needed in 99% of the applications. Boyce-Codd normal form is pretty nice and interesting but in real world applications you’ll never use it. 
  • Object Databases completely disappeared and in some way also the idea that OO methodology/hierarchy could be applied everywhere (just because you are where using OO languages)

Virtualization

  • docker/rkt are slim alternatives to virtualization and virtual machines

Architectures

  • plain old REST API aren’t just a simple way for doing things without having to Corba/Soap ?
  • gRPC : provides corba like features while being 1 order of magnitude more efficent and portable on any platform.

What I’m saying is that the 90s produced a lot of unnecessarily complicated tools and technology which developer just did not need/like which is being progressively substituted with simpler stuff.

Interesting to note that the phrase “Less is more” is originally attributed to Mies Van Der Rohe for his minimalism in architecture design . Looks at his buildings : nothing more than necessary and functional elements are present.

But before him Leonardo da Vinci : “Simplicity is the Ultimate Sophistication”

The Pragmatic Programmer

I think this book is full of valuable thoughts that I would like to recap in this post :

A broken window.
One broken window, left unrepaired for any substantial length of time, instills in the inhabitants of the building a sense of abandonment—a sense that the powers that be don’t care about the building. So another window gets broken. People start littering. Graffiti appears. Serious structural damage begins. In a relatively short space of time, the building becomes damaged beyond the owner’s desire to fix it, and the sense of abandonment becomes reality.

How often this applies to software : you can have the best design guidelines but leaving a broken windows (bad design, wrong decisions, poor code) will slowly propagate that error to all the new code written.

Know when to stop

In some ways, programming is like painting. You start with a blank canvas and certain basic raw materials. You use a combination of science, art, and craft to determine what to do with them. You sketch out an overall shape, paint the underlying environment, then fill in the details. You constantly step back with a critical eye to view what you’ve done. Every now and then you’ll throw a canvas away and start again.
But artists will tell you that all the hard work is ruined if you don’t know when to stop. If you add layer upon layer, detail over detail, the painting becomes lost in the paint.

I read this as don’t over engineer : let your code do the jobs for some time, don’t over refine.

Dry (Don’t Repeat Yourself)

Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.

We all know this right ? But it is not a matter od duplicating code : it is about duplicating knowledge.

Orthogonality

In computing, the term has come to signify a kind of independence or decoupling. Two or more things are orthogonal if changes in one do not affect any of the others. In a well-designed system, the database code will be orthogonal to the user interface: you can change the interface without affecting the database, and swap databases without changing the interface.

You are familiar with orthgonality ( modular, component-based, and layered are synonyms). I read this as : think at your module/component as a service that exposes an API to users :

  • efficient development (no one is waiting for now one else for stuff to be done)
  • easy to test : orthogonal systems can be tested independently
  • easy to understand how to use

To be continued!

Allocating memory inside a Varnish vmod


Writing varnish modules is pretty well documented by the standard varnish documentation, tutorials  and thanks to valuable work from other people here  . There are some areas I felt the need to be further clarified and this post tries to do that.

Allocating memory inside a vmod is tricky if you need to free it when the current Request is destroyed. Here are some ways :

  • per request memory allocation i.e. scope is the request lifetime so memory will be freed when the request is destroyed) :
void WS_Init(struct ws *ws, const char *id, void *space, unsigned len);
unsigned WS_Reserve(struct ws *ws, unsigned bytes);
void WS_MarkOverflow(struct ws *ws);
void WS_Release(struct ws *ws, unsigned bytes);
void WS_ReleaseP(struct ws *ws, char *ptr);
void WS_Assert(const struct ws *ws);
void WS_Reset(struct ws *ws, char *p);
char *WS_Alloc(struct ws *ws, unsigned bytes);
void *WS_Copy(struct ws *ws, const void *str, int len);
char *WS_Snapshot(struct ws *ws);
int WS_Overflowed(const struct ws *ws);
void *WS_Printf(struct ws *ws, const char *fmt, ...) __printflike(2, 3);

This is a per worker thread memory space allocation, no free necessary as data is removed when the request is detroyed. Ex :

VCL_STRING
vmod_hello(const struct vrt_ctx *ctx, VCL_STRING name)
{
   char *p;
   unsigned u, v;

   u = WS_Reserve(ctx->ws, 0); /* Reserve some work space */
   p = ctx->ws->f;         /* Front of workspace area */
   v = snprintf(p, u, "Hello, %s", name);
   v++;
   if (v > u) {
      /* No space, reset and leave */
      WS_Release(ctx->ws, 0);
      return (NULL);
   }
   /* Update work space with what we've used */
   WS_Release(ctx->ws, v);
   return (p);
}

Data is allocated starting with 64k and then when needed in 4k chunks in the cts->ws area. No varnish imposed limit.

  • (since varnish 4.0 up) Private Pointers : a way to have multi-scoped private data per each VCL, TASK. You may access private data either as passed on the VCL function signature or by calling directly VRT_priv_task(ctx, “name”) for example to obtain a per request place to hold :
    • free function
    • pointer to allocated data

This method is very interesting if you need a cleanup function to be called when the varnish request is destroyed.