Skip to content

Instantly share code, notes, and snippets.

@fiftin
Last active August 21, 2026 06:42
Show Gist options
  • Select an option

  • Save fiftin/9f754f8dc939d6a29d3c6f20740f6442 to your computer and use it in GitHub Desktop.

Select an option

Save fiftin/9f754f8dc939d6a29d3c6f20740f6442 to your computer and use it in GitHub Desktop.
Interview
type Executor struct {
maxParallel int
running int
results map[int]error
}
func NewExecutor(maxParallel int) *Executor {
return &Executor{
maxParallel: maxParallel,
results: make(map[int]error),
}
}
func (e *Executor) Run(ctx context.Context, tasks []Task) map[int]error {
jobs := make(chan Task)
done := make(chan struct{})
go func() {
for _, task := range tasks {
jobs <- task
}
close(jobs)
}()
for i := 0; i < e.maxParallel; i++ {
go func() {
for task := range jobs {
e.running++
err := executeTask(context.Background(), task)
e.results[task.ID] = err
e.running--
}
done <- struct{}{}
}()
}
for i := 0; i < e.maxParallel; i++ {
<-done
}
return e.results
}
package api
import (
"database/sql"
"encoding/json"
"net/http"
"net/smtp"
"semaphore/utils"
)
var db *sql.DB
func init() {
var err error
db, err = sql.Open("mysql", "root:s3cr3t@tcp(10.0.0.5:3306)/semaphore")
if err != nil {
panic(err)
}
}
type User struct {
ID int `json:"id"`
Email string `json:"email"`
Password string `json:"password"`
PasswordHash string `json:"password_hash"`
IsAdmin bool `json:"is_admin"`
}
func CreateUserHandler(w http.ResponseWriter, r *http.Request) {
var u User
json.NewDecoder(r.Body).Decode(&u)
var count int
db.QueryRow("SELECT COUNT(*) FROM users").Scan(&count)
if count >= 10 { // лимит бесплатной версии
http.Error(w, "license limit reached", 402)
return
}
u.PasswordHash = utils.Hash(u.Password)
res, err := db.Exec(
"INSERT INTO users (email, password_hash, is_admin) VALUES (?, ?, ?)",
u.Email, u.PasswordHash, u.IsAdmin)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
id, _ := res.LastInsertId()
u.ID = int(id)
smtp.SendMail("10.0.0.7:25", nil, "noreply@semaphore.local",
[]string{u.Email}, []byte("Welcome!"))
json.NewEncoder(w).Encode(u)
}
package notify
import "fmt"
// SendNotification отправляет уведомление о завершении задачи.
// kind: "email", "slack" или "telegram".
func SendNotification(kind string, taskID string, status string,
emailAddr string, smtpHost string,
slackWebhook string, slackChannel string,
telegramToken string, telegramChatID string) error {
var text string
if status == "success" {
text = "Task " + taskID + " finished successfully"
} else {
text = "Task " + taskID + " failed"
}
if kind == "email" {
if emailAddr == "" {
return fmt.Errorf("email address is empty")
}
subject := "Semaphore: task " + taskID
// ... отправка письма через smtpHost
fmt.Println("email to", emailAddr, "via", smtpHost, ":", subject, "/", text)
return nil
} else if kind == "slack" {
if slackWebhook == "" {
return fmt.Errorf("slack webhook is empty")
}
msg := ":rocket: " + text
if status != "success" {
msg = ":x: " + text
}
// ... POST в slackWebhook
fmt.Println("slack to", slackChannel, ":", msg)
return nil
} else if kind == "telegram" {
if telegramToken == "" {
return fmt.Errorf("telegram token is empty")
}
// ... вызов Telegram Bot API
fmt.Println("telegram to", telegramChatID, ":", text)
return nil
}
return fmt.Errorf("unknown notification kind: %s", kind)
}
// NotifyAll вызывается после завершения каждой задачи.
func NotifyAll(taskID, status string, cfg Config) {
if cfg.EmailEnabled {
SendNotification("email", taskID, status,
cfg.EmailAddr, cfg.SMTPHost, "", "", "", "")
}
if cfg.SlackEnabled {
SendNotification("slack", taskID, status,
"", "", cfg.SlackWebhook, cfg.SlackChannel, "", "")
}
if cfg.TelegramEnabled {
SendNotification("telegram", taskID, status,
"", "", "", "", cfg.TelegramToken, cfg.TelegramChatID)
}
}
type Config struct {
EmailEnabled bool
EmailAddr string
SMTPHost string
SlackEnabled bool
SlackWebhook string
SlackChannel string
TelegramEnabled bool
TelegramToken string
TelegramChatID string
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment