Yêu cầu thg 3 17, 2020 3:28 SA 255 0 3
  • 255 0 3
+1

[ask] [PHP] Lỗi function sau chạy trong khi function trước đó chưa chạy xong!

Chia sẻ
  • 255 0 3

Mình có viết

Fun1();
Fun2()

[details="Summary"]

send_notifications($data,$arr_endpoint_id);
set_schedule_notification($notification['notification_id'],$endpoint_start,$endpoint_end);

[/details]

Mà Fun2 chạy trong khi Fun 1 chưa chạy xong dẫn đến tràn > đứng máy chủ.

FULL code : https://throwbin.io/FcNrjAC

Ae xem mình sai chỗ nào với. Mình muốn nó chạy tuần tự 1>500 rồi 500>1000 mà nó chạy 1 phát là 1>1000...

3 CÂU TRẢ LỜI


Đã trả lời thg 3 17, 2020 4:50 SA
+2

Mình thấy lỗi logic trong code của bạn

  • Trong hàm schedule_main() line 70 bạn gọi hàm set_schedule_notification()
  • Trong hàm set_schedule_notification() line 21 bạn gọi ngược lại hàm schedule_main()

=> Điều này dẫn đến vòng lặp vô tận

  • Giải pháp:
  • Dùng vòng lặp while gọi hàm get_schedule_notification() kiểm tra xem có dữ liệu hay không, nếu có gọi hàm schedule_main(), nếu không thì kết thúc
Chia sẻ
Avatar Trúc Mai @Stevendie
thg 3 17, 2020 5:09 SA

Ok hơn rồi. Mà url trang vẫn load nhìn không trực quan lắm. Ah mình thử CURL file này thì hàm vẫn chạy. Update: Vẫn ăn 503, về logic cái này xử lý phức tạp quá 😦

Đã trả lời thg 3 18, 2020 2:04 SA
+1

theo mình hiểu là bạn muốn chạy send_notifications để gửi $data lần lượt cho các id trong $arr_endpoint_id, mỗi lần send xong cho 1 id sẽ sleep(1). Bạn thử loop $arr_endpoint_id, gọi hàm send_notifications cho từng id xem sao. Sau khi loop hết thì sẽ gọi hàm set_schedule_notification(). Mình có sửa lại code trong URL bạn gửi, bạn xem thử xem sao. Thêm chút góp ý là:

  • Mình ko hiểu sao bạn lại gọi ngược lại schedule_main trong set_schedule_notification()
  • Nên đặt tên biến sao cho tựa tên hàm để dễ hiểu hơn. (ví dụ line 51 $notification = get_schedule_notification() nhưng line 65 lại $data = get_notification())
Chia sẻ
Avatar Trúc Mai @Stevendie
thg 3 18, 2020 2:23 SA

Ấy nãy mình online chưa vào xem mà lỡ reset cái code bên kia. Bạn note lại đã sửa gì k 😦 sleep(1) là mình test code ví dụ cái đó sẽ chạy mất 1s mới xong. Về hướng xử lý là mình:

  • Tạo bản tin > ném vào database 2 bảng: bảng nội dung 1 bảng lưu thông tin bản tin ( tiêu đề nội dung), bảng gửi 1 bảng lưu id của bản tin kia, id bắt đầu và id kết thúc. Để thử hiệu năng nên hiện tai là ALL.
  • Chạy file action ( chưa code trên)
  1. Tìm xem có bản tin chưa gửi
  2. Bắt đầu lấy danh sách endpoint 1>200 gửi
  3. Update lại bảng gửi với id bắt đầu+200 nếu nhỏ hơn id cuối thì quay lại 1.

Trình tự như này mà 2 chưa xong 3 đã chạy dẫn đến bị nhân lên .... sv quá tải.

FULL code:

thg 3 18, 2020 6:32 SA

Mình nghĩ là nếu bạn muốn làm theo hướng của bạn thì bạn nên chunk $arr_endpoint_id từ line 69
$send_list = array_chunk($arr_endpoint_id, 100, true); sau đó:

foreach ($send_list as $key => $list)
{
    if (send_notifications($data, $list) === true) // chỗ này đảm bảo send xong 100 id và return true thì code mới chạy
    {
         set_schedule_notification($notification['notification_id'],$endpoint_start,$endpoint_end);
    }
}

cả cụm schedule_main sẽ như sau:

// kiem tra va gui
function schedule_main(){
	if (!($notification = get_schedule_notification())){
        echo "notification schedule null<br/>";
		return false;
	} 
	$endpoint_start = $notification['endpoint_start'];
	$endpoint_end = $notification['endpoint_end'];
    
    if(!($arr_endpoint_id = get_schedule_endpoint_list($endpoint_start,$endpoint_end)))
    {
        echo "arr_endpoint_id null<br/>";
        return false;
    }
    $endpoint_start = $arr_endpoint_id[sizeof($arr_endpoint_id)-1];
    
    if(!($data = get_notification($notification['notification_id']))){
        echo "notification data null<br/>";
        return false;
    } 
    $milliseconds = round(microtime(true) * 1000000);
    $send_list = array_chunk($arr_endpoint_id, 100, true);
    foreach ($send_list as $key => $list)
    {
        if (send_notifications($data, $list) === true) // chỗ này đảm bảo send xong 100 id và return true thì code mới chạy
        {
            set_schedule_notification($notification['notification_id'],$endpoint_start,$endpoint_end);
        }
    }
    $milliseconds=round(microtime(true) * 1000000) - $milliseconds;
    echo "{'success': [{'message': 'Kiểm tra Log ".($milliseconds/1000000)."s'}]}<br/>";
}

Mình nghĩ đằng nào chỗ main này cũng return false khi check ko có notification hay data hay end_point_id nên đẩy các trường hợp false lên trên để return false luôn, khỏi chạy những đoạn dưới cho mất thời gian và code sẽ gọn và nhanh hơn. (Ý kiến cá nhân 😄) Thêm 1 góp ý hơi bị tiểu tiết nhưng bạn nên thống nhất cách viết tên biến nhé. Mình thấy có nhiều chỗ mix giữa camel case và snake case (full code ở Github).

Đã trả lời thg 3 18, 2020 4:08 SA
0

fun2 chạy mà fun1 chưa xong

Php chạy tuần tự => code logic của bạn sai chỗ nào đó thôi. Bạn lên xem lại phần code logic của mình

PS: Mà dòng 23 trên github if ($endpoint_start >= ($endpoint_end-1)) $status= ' , status=2 '; Tại sao $endpoint_end-1 thế bạn (hàm này nếu không nhầm luôn update status=1 ) và mình ko thấy bạn update trường endpoint_end ở chỗ nào cả

Chia sẻ
Avatar Trúc Mai @Stevendie
thg 3 18, 2020 4:19 SA

Phân khúc hiện tại ALL nên: endpoint_end cố định lúc tạo ta bản tin = số endpoint mới nhất trong danh sách đăng ký. Với list >10k thì mỗi lần lấy chạy mình lấy 500 rows

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí