SwooleDistributed 1.7 发布,不需纠结同步和异步

来源: 投稿
作者: 白_猫
2017-01-04 18:08:00

SwooleDistributed 1.7更新

  • 修复redis和mysql的一些bug,统一同步和异步的调用方法和回应结果的结构。redis基本所有的命令均已测试和统一。

  • 增加了单元测试模块。

  • 增加了mysql,redis,controller的单元测试用例。

  • 已知bug修复。

SwooleDistributed 1.6更新

通过协程写法统一异步和同步客户端。

4大模块Model,Controller,View,Task,Model处理异步简单事务,Task处理同步耗时事务,原本开发者需要在Model中使用异步客户端(异步redis,异步mysql),在Task中使用同步客户端(redis扩展,mysql-pdo扩展),代码风格完全不一致,无法重用。现在最新版本的SD框架将托管异步和同步客户端的调用,使用协程模式书写的代码在Model和Task中完全通用,并且Task和Model之间可以完成互相调用,代码100%可重用,采用协程代码风格开发者将可以忽略异步与同步的区别。通过task调用model的方法可以很容易将一个耗时任务优化到任务队列中而不需要更改任何代码。

通过协程的方法屏蔽异步同步的区别

同步

sd框架中Task就是一个典型的同步案例。task中不允许调用异步的api。

异步

sd框架中除了task基本都是异步的,异步最好使用异步api达到更高的效率。

如何选择

在1.6版本之前,task中如果使用mysql和redis都必须调用同步的客户端,而且同步客户端和异步客户端的调用方法以及返回结构都不一样,这样model和task的代码完全无法重用,也更不可能通过task去调用model。

福利

1.6版本后实现了框架进行异步和同步的选择,1.7版本对于这种新的方式进行了优化和完善。 通过协程的方式写的代码可以同时在modle和task中运行。也不用关心同步和异步的写法不同,他们的调用方式和返回值都保持绝对的一致。

$value = yield $this->redis_pool->getCoroutine()->setex('test', 10, 'testRedis');

比如这段代码在model和task中均能被正确的执行。

同时在task中也可以调用model的方法。

$testModel = $this->loader->model('TestModel', $this);
$result = yield $testModel->test_task();

至此难为程序员的异步和同步的区别现在被完美的解决了。

单元测试

仿照PHPUnit提供一个简易的单元测试框架

TestCase

这是基类,请继承。

方法

test开头的public方法才能作为测试用例,其余将被忽略。

setUpBeforeClass与tearDownAfterClass

setUpBeforeClass() 与 tearDownAfterClass() 模板方法将分别在测试用例类的第一个测试运行之前和测试用例类的最后一个测试运行之后调用

setUp与tearDown

测试类的每个测试方法都会运行一次 setUp() 和 tearDown() 模板方法

coroutineRequestHttpController

启动一个http的模拟访问。

$testRequest = new TestRequest('/TestController/test');
        $testResponse = yield $this->coroutineRequestHttpController($testRequest);
        $this->assertEquals($testResponse->data, 'helloworld');

TestRequest中可以设置请求的一些方法。 testResponse为返回的数据。其中data为返回的值,其余见类成员。

coroutineRequestTcpController

启动一个tcp的模拟访问

if ($this->config['server']['pack_tool'] != 'JsonPack') {
            $this->markTestSkipped('协议解包不是JsonPack');
        }
        $data = ['controller_name' => 'TestController', 'method_name' => 'test', 'data' => 'helloWorld'];
        $reusult = yield $this->coroutineRequestTcpController($data);
        $this->assertCount(2, $reusult);

$data传进去的是一个协议体

$result是返回的服务器具体操作步骤,详情可以自己打印。

特别注意这是模拟的方式,所以服务器不会产生任何的send操作,只是记录操作。

使用controller内提供的方法才能被记录,get_instance()的方法不会被记录,可能还会产生错误。

markTestSkipped

表示该测试被跳过。

@needTestTask

标注needTestTask

被标注的将会在测试的时候额外进行task同步测试。

@codeCoverageIgnore

标注codeCoverageIgnore

被标注的会在测试的时候被忽略

@depends

标注depends

对测试方法之间的显式依赖关系进行声明。

被标注的将产生依赖,和phpunit一样

public function testEmpty()
    {
        $stack = [];
        $this->assertEmpty($stack);

        return $stack;
    }

    /**
     * @depends testEmpty
     */
    public function testPush(array $stack)
    {
        array_push($stack, 'foo');
        $this->assertEquals('foo', $stack[count($stack)-1]);
        $this->assertNotEmpty($stack);

        return $stack;
    }

    /**
     * @depends testPush
     */
    public function testPop(array $stack)
    {
        $this->assertEquals('foo', array_pop($stack));
        $this->assertEmpty($stack);
    }

在上例中,第一个测试, testEmpty(),创建了一个新数组,并断言其为空。随后,此测试将此基境作为结果返回。第二个测试,testPush(),依赖于 testEmpty() ,并将所依赖的测试之结果作为参数传入。最后,testPop() 依赖于 testPush()。

各种简易断言

  • assertEquals

  • assertEmpty

  • assertNotEmpty

展开阅读全文
点击加入讨论🔥(3) 发布并加入讨论🔥
3 评论
20 收藏
分享
返回顶部
顶部