A simple web-based task manager written in GO for Unix-based systems including Android.

When I worked in a firm that deals with electronic government services, I was always surprised that the systems we were building or upgrading became extremely complex with time. They became friable and unreliable with a huge amount of dependencies. Like the red giant, the system swelled and could collapse at any time.
The development of systems is not only increasing functionality, but also reducing and optimizing systems.
It seems to me that the same thing happens in the it sphere. Take a look at Windows 8.1, this is a victim of marketing ideas. Remember the Azureus Torrent Client? Now this is a whole media harvester Vuze.
I always wanted to write a program for myself. Something simple and not complicated, working through the web interface, something like the task manager top, only working through the browser. There are a lot of systems that can perform this kind of functionality, but they are from the series:
')
Put PHP + Apache + MySQL + ... something else. Those. In my opinion, too "bloated."
When I chose a language, I turned my attention to GO. Recently, a lot has been written about him on the “Habré”.
As soon as I began to read books and articles about him, I immediately fell in love with this stunning laconic and natural language. I was amazed at how much, the opinion of the creators coincided with my
Here are some examples:
- There are no templates in it. Patterns are a legacy of macros. Solving the problem of generalizing algorithms and classes, the use of templates, complicated the understanding of the code by an order of magnitude.
- There is no inheritance in GO. As there is no multiple inheritance, so there is no ordinary inheritance. For the place of inheritance, clearer and clearer embedding mechanisms and interfaces are used.
- By default, the compiled file is statically linked. This means that it can be run on any system without worrying about dependencies.
- Cross-compilation is supported out of the box.
- There is unit testing.
To get information about the processes and statistics of the system, wtop uses the proc virtual file system. Therefore, it will work on any system that uses it (including android and ... I'm not sure of Plan9). The backend uses the http-server embedded in go. And as a frontend html / java script. To exchange data between frontenf and backend json messages are used. To run it, just run the executable file and go to
xxxx in the browser: 9977 / index.html


The screenshot above shows that at the time of gathering information, on a phone with a dual-core Texas Instruments 4430 processor, 1.2 GHz, wtop consumes about 10% of processor time and only 4.5 megabytes of memory, which is a little. On the desktop, with the ubuntu operating system, 0.5% of the CPU time and the same 4.5 megabytes of memory. If within 5 seconds there was no request from the client, then he falls asleep until the new json request wakes him up.
Further I will describe what constructions the main points are used in the program code .
Upon receiving the http.Request object, the ProduceJsonRequest method “parses” the request body and creates the request object. Which in turn is dispatch using Dispatch:
func (fabric *JsonFabric) ProduceJsonRequest(request *http.Request) (Request, error) { bodyData, err := ioutil.ReadAll(request.Body) if err != nil { stErr := "error: Can't read request body" log.Println(stErr) return nil, errors.New(stErr) } defer request.Body.Close() var basicRequest BasicRequest err = json.Unmarshal(bodyData, &basicRequest) if err != nil { stErr := "error: Can't parse basic data" log.Println(stErr) return nil, errors.New(stErr) } switch basicRequest.Type { case ServiceStatus: var serviceStateRequest ServiceStateRequest err := json.Unmarshal(bodyData, &serviceStateRequest) if err != nil { stErr := "error: Can't parse service state request" log.Println(stErr) return nil, errors.New("error: Can't parse service state request") } return serviceStateRequest, nil ...... ...... ...... } return nil, errors.New("error: Unknown request type")
func (requestSelector *RequestSelector) Dispatch(request Request, responseWriter http.ResponseWriter, httpRequest *http.Request) error {
When distributing a query, a dictionary is searched for the corresponding handler, followed by a call to it.
There is nothing interesting in processing the request.
Interest is provided by the BatchJob structure. Using it in our object, we can ensure the periodicity of performing certain actions (in our case, measurements).
type BatchJob struct { Job func() runJob bool done chan bool } func (batchJob *BatchJob) Start() error { if batchJob.runJob { return errors.New("error: can't stop not stopped job") } if batchJob.Job == nil { return errors.New("error: empty job function") } if !batchJob.runJob { batchJob.done = make(chan bool, 1) } go batchJob.execution(batchJob.done) batchJob.runJob = true return nil } func (batchJob *BatchJob) IsRunning() bool { return batchJob.runJob } func (batchJob *BatchJob) Stop() error { if !batchJob.runJob { return errors.New("error: can't stop not stopted job") } batchJob.runJob = false isDone := <-batchJob.done if isDone { close(batchJob.done) return nil } return errors.New("error: failed stop job") } func (batchJob *BatchJob) execution(done chan bool) { for { if batchJob.runJob { batchJob.Job() } else { done <- true return } } }
For this, each request handler has an object of the BatchJob structure. The Job field is instantiated with a reference to the measurement function.
top.collectInfoJob.Job = top.collectInfo top.lastRequestTime = time.Now() err := top.collectInfoJob.Start()
As I noted above, if no one interrogates the service after 5 seconds, he will fall asleep.
In my opinion, the program was very simple and logical. Each of its modules performs a specific function and can operate independently of each other.
All source codes are available at the GitHub repository at
github.com/Loafter/WebTop .
From myself I would like to say once again that GO is an amazing and powerful language. I hope he will take a dominant role among the languages ​​of the new generation.
For those who read to the end, I cite links to compiled binaries for different architectures.
index.html - web interface;
wtop-armv5-linux - the version for Linux (Android) arm v5;
wtop-armv6-linux - the version for Linux (Android) arm v6;
wtop-x64-linux - Linux version (Ubuntu ... etc) X86-64.