Wednesday, October 28, 2015

Introducing the prooph-components for DDD, EventSourcing & CQRS in PHP

Prooph EventStore v6.0 beta 1 is now available with the final version coming along very soon. Time to write a short blogpost about what's new in it.

- History Replay
- Snapshot Support
- Apply Events Late
- EventStream Iterator
- interop config support
- AggregateRepository Factory

History Replay

The read model can be regenerated from history at any point in time by replaying recorded events.

Snapshot Support

If you have way to many events to replay in order to reconstruct the aggregate root, why not take a snapshot? The prooph components ship with different snapshot adapters like MongoDB, Doctrine DBAL and even Memcached backends. So replaying of thousands of events is not a burden any more.

Apply Events Late

Events are only applied after transaction commit to ensure that the aggregate root can never reach an invalid state. This is especially useful for long-running CLI scripts.

EventStream iterator

The event stream is now implemented as an Iterator instead of a simple array. This reduces the memory usage a lot when replaying big event streams.

Interop config support

The components ship with ready-to-use container-interop factories using https://github.com/sandrokeil/interop-config. This makes it really simple to configure the factories.

Want more? Visit getprooph.org to check out the documentation or try out our demo application proophessor-do. Pick up a task and at the sample application to get started with event sourcing and get your hands a little dirty.

Integretion of RabbitMQ in Zend Framework 2

When it comes to asynchronous processing in php, there is a robust way to do it, with RabbitMQ. Using RabbitMQ (an implementation of the AMQP protocal with some nice additional features) is pretty straightforward using the PHP AMQP Extension. What was missing so far was a nice Zend Framework 2 Integration, a generic consumer implementation, a simple RPC-client & -server implementation.

The producer interface is very simple:
namespace HumusAmqpModule;

interface ProducerInterface
{
    /**
     * @param string $body
     * @param string $routingKey
     * @param array|\Traversable|MessageAttributes|null $attributes
     */
    public function publish($body, $routingKey = '', $attributes = null);

    /**
     * @param array $bodies
     * @param string $routingKey
     * @param array|\Traversable|MessageAttributes|null $attributes
     */
    public function publishBatch(array $bodies, $routingKey = '', $attributes = null);
}
On the other hand we have an extendable consumer interface:
namespace HumusAmqpModule;

use AMQPChannel;
use AMQPEnvelope;
use AMQPQueue;

interface ConsumerInterface
{
    /**
     * Flag for message ack
     */
    const MSG_ACK = 1;

    /**
     * Flag for message defer
     */
    const MSG_DEFER = 0;

    /**
     * Flag for reject and drop
     */
    const MSG_REJECT = -1;

    /**
     * Flag for reject and requeue
     */
    const MSG_REJECT_REQUEUE = -2;

    /**
     * Start consumer
     *
     * @param int $msgAmount
     */
    public function consume($msgAmount = 0);

    /**
     * @return bool
     */
    public function flushDeferred();

    /**
     * @param AMQPEnvelope $message
     * @param AMQPQueue $queue
     * @return bool|null
     */
    public function handleDelivery(AMQPEnvelope $message, AMQPQueue $queue);

    /**
     * @return void
     */
    public function handleShutdownSignal();
}
The consumer supports the following:

- defer message for later decision whether to ack or nack
- ack & nack blocks of messages
- configure prefetch count
- automatic exchange and queue creation
- set callback for handling delivery of messages
- set callback for handling flush deferred messages
- set error callback
- set configurable logger
- idle timeout
- non-blocking
- configurable wait timeout
- unix signal handler support
- generic cunsumer controller and cli integration
- supervisor support
- integration in HumusSupervisorModule

Even more to come....

There is also a manual at Read the Docs and a Demo-Module incl. RPC-Client & -Server Example. Thew manual and the demo module will help you getting startet with Queuing in Zend Framework 2 without any pre-existing knowledge and guide you how to create topic-exchanges, header-exchanges, fanout-exchagesn, how to set up dead-lettering, message timeout, and so on.

Your contributions are welcome!

Monday, February 23, 2015

Lenovo Yoga 3 Pro rotate script for linux

TouchscreenDevice='ATML1000:00 03EB:8A10'
TouchpadDevice='SYNA2B22:00 06CB:2714'

These are the settings for my lenovo yoga 3 pro. If this is not working for you, find your Touchscreen and Touchpad device with xinput.

See also my gist at: https://gist.github.com/prolic/21673f0909c0cb5e2114
 
With credits to Ruben Barkow: https://gist.github.com/rubo77/daa262e0229f6e398766

#!/bin/bash
# This script rotates the screen and touchscreen input 90 degrees each time it is called, 
# also disables the touchpad, and enables the virtual keyboard accordingly

# by Ruben Barkow: https://gist.github.com/rubo77/daa262e0229f6e398766

#### configuration
# find your Touchscreen and Touchpad device with `xinput`
TouchscreenDevice='ATML1000:00 03EB:8A10'
TouchpadDevice='SYNA2B22:00 06CB:2714'

if [ "$1" = "--help"  ] || [ "$1" = "-h"  ] ; then
echo 'Usage: rotate-screen.sh [OPTION]'
echo
echo 'This script rotates the screen and touchscreen input 90 degrees each time it is called,' 
echo 'also disables the touchpad, and enables the virtual keyboard accordingly'
echo
echo Usage:
echo ' -h --help display this help'
echo ' -j (just horizontal) rotates the screen and touchscreen input only 180 degrees'
echo ' -n always rotates the screen back to normal'
exit 0
fi

touchpadEnabled=$(xinput --list-props "$TouchpadDevice" | awk '/Device Enabled/{print $NF}')
screenMatrix=$(xinput --list-props "$TouchscreenDevice" | awk '/Coordinate Transformation Matrix/{print $5$6$7$8$9$10$11$12$NF}')

# Matrix for rotation
# ⎡ 1 0 0 ⎤
# ⎜ 0 1 0 ⎥
# ⎣ 0 0 1 ⎦
normal='1 0 0 0 1 0 0 0 1'
normal_float='1.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,1.000000'

#⎡ -1  0 1 ⎤
#⎜  0 -1 1 ⎥
#⎣  0  0 1 ⎦
inverted='-1 0 1 0 -1 1 0 0 1'
inverted_float='-1.000000,0.000000,1.000000,0.000000,-1.000000,1.000000,0.000000,0.000000,1.000000'

# 90° to the left 
# ⎡ 0 -1 1 ⎤
# ⎜ 1  0 0 ⎥
# ⎣ 0  0 1 ⎦
left='0 -1 1 1 0 0 0 0 1'
left_float='0.000000,-1.000000,1.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000'

# 90° to the right
#⎡  0 1 0 ⎤
#⎜ -1 0 1 ⎥
#⎣  0 0 1 ⎦
right='0 1 0 -1 0 1 0 0 1'

if [ $screenMatrix == $normal_float ] && [ "$1" != "-n" ]
then
  echo "Upside down"
  xrandr -o inverted
  xinput set-prop "$TouchscreenDevice" 'Coordinate Transformation Matrix' $inverted
  xinput disable "$TouchpadDevice"
  # Remove hashtag below if you want pop-up the virtual keyboard  
  #onboard &
elif [ $screenMatrix == $inverted_float ] && [ "$1" != "-j" ] && [ "$1" != "-n" ]
then
  echo "90° to the left"
  xrandr -o left
  xinput set-prop "$TouchscreenDevice" 'Coordinate Transformation Matrix' $left
  xinput disable "$TouchpadDevice"
  #killall onboard
elif [ $screenMatrix == $left_float ] && [ "$1" != "-j" ] && [ "$1" != "-n" ]
then
  echo "90° to the right"
  xrandr -o right
  xinput set-prop "$TouchscreenDevice" 'Coordinate Transformation Matrix' $right
  xinput disable "$TouchpadDevice"
  #killall onboard
else
  echo "Back to normal"
  xrandr -o normal
  xinput set-prop "$TouchscreenDevice" 'Coordinate Transformation Matrix' $normal
  xinput enable "$TouchpadDevice"
  #killall onboard
fi

Friday, July 19, 2013

Minifesto - MANIFESTO FOR MINIMALIST SOFTWARE ENGINEERS

  • Fight for Pareto's law, look for the 20% of effort that will give you the 80% of results.
  • Prioritize, minimalism isn't about not doing things but about focusing first in the important.
  • Perfect is enemy of good, first do it, then do it right, then do it better.
  • Kill the baby, don't be afraid of starting all over again. Fail soon, learn fast.
  • Add value. Think constantly how you can help your team and position yourself in that field/skill.
  • Basics, first. Follow always a top-down thinking starting by the best-practises of CS.
  • Think different. Simple is harder than complex, which means you'll need to use your creativity.
  • Synthesis is the key of communication. We have to write code for humans not machines.
  • Keep it plain. Try to keep your designs with few layers of indirection.
  • Clean kipple and redundancy. Minimalism is all about removing distractions.

I am currently working on the german translation and will get the russian translation from a friend, too.

Monday, February 25, 2013

Sending stream responses with Zend Framework 2, Part 1

Sending stream responses is a new feature in Zend Framework 2.1. This short introduction will help you getting startet on how to send stream responses in Zend Framework 2.
Most times an application would deliver file downloads or video streaming with static assets, delivered directly frm Apache or Nginx. But sometimes there are restrictions: Only logged-in users should be able to download this file, watch this content, perhabs even a more complicated permission system. Then the application needs to do some permission checks and stream the response.
In this example we assume a simple file download, we deliver the file as stream response, because this is much less memory consuming and more efficient, compared to grabbing the file content and pushing it to the response body of the default response object.

namespace Application\Controller;

use Zend\Http\Headers;
use Zend\Http\Response\Stream;
use Zend\Mvc\Controller\AbstractActionController;

class IndexController extends AbstractActionController
{
    public function fileAction()
    {
        $file = '/path/to/my/file.txt';
        
        $response = new Stream();
        $response->setStream(fopen($file, 'r'));
        $response->setStatusCode(200);
        $response->setStreamName(basename($file));

        $headers = new Headers();
        $headers->addHeaders(array(
            'Content-Disposition' => 'attachment; filename="' . basename($file) .'"',
            'Content-Type' => 'application/octet-stream',
            'Content-Length' => filesize($file)
        ));
        $response->setHeaders($headers);
        return $response;
    }
}

Even more complex use cases with download resume and speed limits are also possible in the future, but this is part of my next blog post about this topic. However you can see how easy it is to send stream responses with Zend Framework 2. As we return the response object directly in the controller, no view is created and rendered, too, so this is really a very fast operation.

Saturday, February 2, 2013

List of current php version in major linux distros

I tried to make a list of current php versions in major linux distributions. Please feel free to correct or add additional one per comment.

Distribution PHP Version
Ubuntu 16.04 Xenial 7.0.4
Ubuntu 15.10 Willy 5.6.11
Ubuntu 14.04 LTS Trusty 5.5.9
Ubuntu 12.04 LTS Precise 5.3.10
Ubuntu 12.10 Quantal
Debian 8 Jessie
5.4.6
5.6.14
Debian 7.5 Wheezy 5.4.4
Debian 6.0.6 Squeeze 5.3.3
Cent OS 6.3 5.3.3
Arch Linux 5.4.11
Fedora 18 5.4.9
Fedora 17 5.4.1
Mandriva 2011 5.3.20
Mandriva 2010 5.3.2
Mageia 2 5.3.19
OpenSUSE 12.2 5.3.15
OpenSUSE 13.1 5.4.20
OpenSUSE 13.2 5.6.1
Slackware 14 5.4.7
PCLinuxOS 5.3.8
Red Hat (Enterprise) Linux 6.3 5.3.3
Red Hat (Enterprise) Linux 7.0 RC 5.4.16
SUSE Linux Enterprise System 11 SP1 5.2.6
SUSE Linux Enterprise System 11 SP2 5.2.14
SUSE Linux Enterprise System 11 SP3 5.3.17

Thursday, January 10, 2013

Using git-svn for projects with many branches

About branches: Git-svn would normally clone all revisions from all branches by default. This is a time-consuming process, so I strongly recommend adding only those branches, that you need for your work.
We don't specify a branches section in our git configuration, instead we are attaching branches as new remotes. That also means, that we can't create or delete branches on a svn server, they have to be created with the corresponding svn commands.
svn cp /trunk /branches/
svn rm /branches/
1) Cloning the repository, checking out trunk

First create a directory where you want your git repository to be on your harddrive, than initialize a new git repository.
mkdir gitsvn
cd gitsvn
git init
Next you have to edit your git config and add the trunk as svn-remote.

edit .git/config and add:
[svn-remote "svn"]
        url = http:///svn/trunk
        fetch = :refs/remotes/git-svn
Next you clone the repository. This will check all SVN revisions and start a download for every revision of every file of the trunk, so this will take a while.
git svn fetch
You end up with a local branch "master" that tracks the svn remote "trunk". Type "git svn info" to show information.
git svn info
2) Keeping things up to date

You should never work on the master branch, that one is only reflecting the trunk, it's a mirror, so please never change files here. Just update the master to reflect the trunk, that's all.
git svn fetch
git svn merge trunk –ff
The --ff flag forces a fast-forward.

3) Creating new local branches and rebase

Sometimes, you just want to create a new local branch and work on it. (Perhabs a small bugfix branch, that immediatly gets merged into trunk.)
git checkout -b bugfixbranch trunk
... do some work …
git commit -m "nice explaining commit message"
All unit tests are good, and you want to push that branch perhabs directory to svn trunk. But first, we need to rebase. Someone else could have made commits to trunk in the meantime, so you have to apply his changes first, than yours, that means rewriting your local history.
git svn fetch
git rebase -i trunk
.. now you have the choice, you can pick, reword, edit, squash and fix commits …
git svn dcommit –dry-run
.. it's always recommended to make a dry-run first, so you don't push to the wrong location accidentialy
git svn dcommit
4) Adding a new svn remote branch

Because we have so many branches, that git would force you to download them all, we just specify the explicit branches we want to track.
git config --add svn-remote.branchname.url http:///svn/branchname
git config --add svn-remote.branchname.fetch :refs/remotes/branchname
git svn fetch branchname [-r]
git checkout -b localbranchname -t branchname
git svn rebase branchname
I recommend that you specify the revision number here, otherwise git will download every revision, starting with 0 first. If your branch was created at revision 100000, you will have to wait a long time.
git checkout -b localbranchname branchname
git svn info
5) Reintegrating a single commit into trunk

In the most easiest case, you have a branch with just one single commit, so you can just cherry-pick it.
git log -2
Output:
commit 2db1182ddc0e85b3a9c468bd7610a58c3bb99d0a
Author: sascha.prolic 
Date:  Tue Jan 8 11:37:29 2013 +0000
    Nice explaining commit message

git-svn-id: http:///svn/branches/branchname@100000 d12c8f96-4347-4129-8f7d-0f3f6588512b

commit c56d7da69e96a662aa9aad8cd394a381bad64807
Author: sascha.prolic 
Date:  Tue Jan 8 16:08:26 2013 +0000
    created branch

git-svn-id: http:///svn/branches/branchname@100000 d12c8f96-4347-4129-8f7d-0f3f6588512b
As you can see, the first commit is "c56d7da69e96a662aa9aad8cd394a381bad64807", but that one is just the svn copy, we don't want to merge this, so only "2db1182ddc0e85b3a9c468bd7610a58c3bb99d0a" is interessting. Lets change to master, update, run the unit tests and commit.
git checkout master
git svn fetch
git merge trunk –ff
git cherry-pick 2db1182ddc0e85b3a9c468bd7610a58c3bb99d0a
... run unit tests
git svn dcommit


6) Reintegrate a branch into trunk
git checkout -b mergebranch branchname
git svn fetch
git rebase -i trunk
Your editor should pop up with something like this in it:
pick 0c70bbe created new branch
pick a5bf234 branchname foo
pick d24360d branchname bar
Note, that we don't want to merge "0c70bbe", because that would was the svn cp command. Just delete this line. Save the file, and exit. You can even squash commit or edit commit messages. Run the unit tests again.
git checkout master
git merge trunk –ff
git merge mergebranch
git svn dcommit
7) Delete the branch checkout

The following command sequence will delete (locally only) the SVN branch and its history:
git branch -D local-branch
git branch -D -r branch
rm -rf .git/svn/branch
git gc
To remove the branch on the svn server, remove it with svn rm <branchurl>.

8) Converting a local branch into a remote branch

Basically all it amounts to is a rebase, with some svn trickery.

svn cp /trunk /branches/final-remote-name
Next you add that branch to your git config.

git checkout local-feature-branch   # This is the local branch where your prototype feature is committed.
git checkout -b final-local-name  # This makes the local branch derived from your local feature branch that will eventually become the branch that tracks the remote svn branch.
git svn info  # This will say you are following trunk.
git rebase remotes/final-remote-name
Verify
git log
git svn info