11package fcfs
22
33import (
4+ "context"
45 "runtime"
56
7+ "go.uber.org/zap"
8+
69 "github.com/PythonHacker24/linux-acl-management-backend/config"
710 "github.com/PythonHacker24/linux-acl-management-backend/internal/session"
11+ "github.com/PythonHacker24/linux-acl-management-backend/internal/transprocessor"
812)
913
1014/* spawns a new FCFS scheduler */
11- func NewFCFSScheduler (sm * session.Manager ) * FCFSScheduler {
15+ func NewFCFSScheduler (sm * session.Manager , processor transprocessor. TransactionProcessor ) * FCFSScheduler {
1216 /* calculate max workers */
1317 maxProcs := runtime .GOMAXPROCS (0 )
1418 maxWorkers := config .BackendConfig .AppInfo .MaxWorkers
@@ -30,5 +34,61 @@ func NewFCFSScheduler(sm *session.Manager) *FCFSScheduler {
3034 curSessionManager : sm ,
3135 maxWorkers : maxWorkers ,
3236 semaphore : make (chan struct {}, maxWorkers ),
37+ processor : processor ,
3338 }
3439}
40+
41+ /* run the fcfs scheduler with context */
42+ func (f * FCFSScheduler ) Run (ctx context.Context ) error {
43+ for {
44+ select {
45+
46+ /* check if ctx is done - catchable if default is not working hard (ideal scheduler) */
47+ case <- ctx .Done ():
48+ return nil
49+
50+ /* in case default is working hard - ctx is passed here so it must attempt to quit */
51+ default :
52+ /* RULE: ctx is propogates all over the coming functions */
53+
54+ /* get next session in the queue (round robin manner) */
55+ curSession := f .curSessionManager .GetNextSession ()
56+ if curSession == nil {
57+ /* might need a delay of 10 ms */
58+ continue
59+ }
60+
61+ /* check if transaction queue of the session is empty */
62+ curSession .Mutex .Lock ()
63+ if curSession .TransactionQueue .Len () == 0 {
64+ curSession .Mutex .Unlock ()
65+ continue
66+ }
67+
68+ /* get a transaction from the session to process */
69+ transaction := curSession .TransactionQueue .Remove (curSession .TransactionQueue .Front ())
70+ curSession .Mutex .Unlock ()
71+
72+ /* block if all workers are busy */
73+ f .semaphore <- struct {}{}
74+
75+ /* go routine is available to be spawned */
76+ go func (curSession * session.Session , transaction interface {}) {
77+ /* defer clearing the semaphore channel */
78+ defer func () { <- f .semaphore }()
79+
80+ /*
81+ process the transaction
82+ * processTransaction handles transaction processing completely
83+ * now it is responsible now responsible to execute it
84+ * role of scheduler in handling transactions ends here
85+ */
86+ if err := f .processor .Process (ctx , curSession , transaction ); err != nil {
87+ zap .L ().Error ("Faild to process transaction" ,
88+ zap .Error (err ),
89+ )
90+ }
91+ }(curSession , transaction )
92+ }
93+ }
94+ }
0 commit comments