近期找到的語音通訊軟體,音質、順暢程度感覺最好的是 Google Duo,但是在行動裝置上運作起來,可以說是個非常吃系統資源的怪獸 (僅次於 LINE 和 Facebook 吧),所以打算找找看有沒有 Desktop 的版本。
沒想到 Google Dou 提供的不是 Desktop 版本 …
感覺目前資訊產業從個人電腦,又慢慢轉回中央主機系統的架構,只是 terminal 變成彩色瀏覽器而已。
軟體開發、伺服器和生活瑣事
近期找到的語音通訊軟體,音質、順暢程度感覺最好的是 Google Duo,但是在行動裝置上運作起來,可以說是個非常吃系統資源的怪獸 (僅次於 LINE 和 Facebook 吧),所以打算找找看有沒有 Desktop 的版本。
沒想到 Google Dou 提供的不是 Desktop 版本 …
感覺目前資訊產業從個人電腦,又慢慢轉回中央主機系統的架構,只是 terminal 變成彩色瀏覽器而已。
最近在研究 Python,下載了 RPIO 來安裝:
$ wget http://...... -O RPIO.zip
$ unzip RPIO.zip
$ python RPIO/setup.py install
....
running install
running bdist_egg
error: error in 'egg_base' option: 'source' does not exist or is not a directory
弄了半天,才知道有路徑問題,要先切到 package 根目錄再安裝才會成功:
$ cd RPIO
$ python setup.py install
沒寫過 Python 直接衝 GPIO 有越級打怪的感覺,不知道機器會不會被我搞爛 Orz
理論上,各個 test case 不應該互相影響,所以 PHPUnit 設計的 fixtures 像是 setUp() 和 tearDown() 都會在各個 test case 前後執行。
簡單做個測試:
<?php
use PHPUnitFrameworkTestCase;
class LibTest extends TestCase
{
public function setUp(): void
{
$this->data = null;
}
public function tearDown(): void
{
$this->data = null;
}
public function testOne()
{
$this->data = 123;
$this->assertEquals(123, $this->data);
return $this->data;
}
/**
* @depends testOne
*/
public function testTwo($data)
{
$this->assertEquals(123, $this->data);
}
}
// -----
PHPUnit 8.2.3 by Sebastian Bergmann and contributors.
.F
即使在 test case 加上 @depends 標記,fixture 也會運作,所以若是要讓下一個 test case 繼續使用的測試值,都必須用 return 的方式傳值。
—-
另外,Laravel 提供的 testing tools 也有相同的行為。例如:「RefreshDatabase」,在 test case 執行結束以後就會把資料清空,因此如果要對 DB 做多像檢查,就必須在同一個 test case 中建立多個 assertions (個人不喜歡這樣做),不然即使加上 @depends,DB 中的資料也會被 refresh 掉。
現在有個 controller 收到 HTTP POST data 以後才會動作,且這個 controller 為 AJAX controller,沒有 view 沒辦法用 Selenium 測試:
class TargetController extends Controller
{
public function doSomething(Request $req)
{
// do something ....
}
}
要測試的話,其實可以透過一些工具手動測試,像是 PostMan 等類似的工具。但這種測試會遇到一些問題:Middle 有檢查使用者身份、需要拿到 access token 才能進 controller 等等。這樣會讓測試多了不少不確定因素 (變因),導致測試結果不準確。
要進行測試較好的方法,就是建立一個 HTTP request 來模擬實際情況:
$req = new lluminateHttpRequest();
$ctrl = new TargetController()
$result = $ctrl->doSomething($req);
不過可惜的是 Request 這個類別,設計原始的用意是從 $_GET、$_POST、$_FILE 等全域變數整理成物件方便 access,所以若要在 request 中加入參數,目前只能透過 replace() 來增加。例如需要新增 key/value pair,必須這樣撰寫:
$request->replace([
'key' => 'value',
]);
至於模擬檔案上傳 …. 我還在找方法,確定了以後再來寫筆記。
Ref:
若 task 無法立即完成,為了提高 UX,通常不會讓使用者在線上等待 task 完成,而是告知使用者 task 已經在背景執行,完成後再通知使用者。
這個情境下,系統通常是這樣實作:建立一個 queue,將等待處理的 task 全部放進 queue 中,並讓 idle 的 consumer 自動從 queue 中取得一個 task 來執行 (當然也有可能是用 dispatch 的方式)。
假設有 A、B、C 三個使用者的 task 的放進 queue 來處理,一般情況下 queue 的狀態大概會向下面這個樣子:
=> A, C, B, C, A, A, C, A, B, C, B =>
但大多時候工作的分配通常不會這個平均,有時 A 使用者會需要大量處理資料,於是 queue 就會成下面這個樣子:
=> A, C, B, C, A, A, A .... (x1000), A, A, C, A, B, C, B =>
若這個情況下仍然使用相同的 consume 機制,會變成大多數的時間都在處理 A 的 tasks,導致 B、C 使用者的 task 被 (無限) 延後。
在一般狀態下這樣不是一件好事,就像去餐廳買飯,因為前面有個 50 人份的訂單排在你前面,就導致你買一個便當也要等一個多小時。在我自己碰到的狀況,這個時候餐廳通常會有二種作法:
將上面提到的情況改用在 task queue 上,若遇到類似的問題,則可以考慮不同處理 queue 的方法。
例如為不同用途、類型的 task 分別建立不同的 queue,而每次都從個別的 queue 做一次 de-queue,這樣就不會因為 queue-A 大量的 task 卡住其他的 task:
queue for A: t999, t998, t997, ...., t3, t2, t1
queue for B: t3, t2, t1
queue for C: t6, t5, t4, t3, t2, t1
另外也可以考慮使用類似 Laravel API rate limit 的功能,分別記錄每個時段中,各類型的 task 共處理了多少次,若超過限制,則將原本 de-queue 出來準備處理的 task 在 in-queue 輪到較晚處理:
step 1: C, B, A, A, A, A, A, C, A
step 2: C, B, A, A, A, A, A, C
step 3: C, B, A, A, A, A, A
step 4: C, B, A, A, A, A
step 5: C, B, A, A, A // 連續處理二個 A task 了,到達上限
step 6: A, C, B, A, A
step 7: A, A, C, B, A
step 8: A, A, A, C, B
step 8: A, A, A, C
....
當然,用錢可以解決的問題都不是問題。把廚房加個 100 倍大,請一批廚師來炒菜,原本那 50 個訂單就根本沒在怕的啦 XD