aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/schedule
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/schedule')
-rw-r--r--pkg/schedule/model.go72
-rw-r--r--pkg/schedule/parse.go205
-rw-r--r--pkg/schedule/service.go116
3 files changed, 0 insertions, 393 deletions
diff --git a/pkg/schedule/model.go b/pkg/schedule/model.go
deleted file mode 100644
index fcf39a5..0000000
--- a/pkg/schedule/model.go
+++ /dev/null
@@ -1,72 +0,0 @@
-package schedule
-
-import "time"
-
-type Schedule struct {
- Conference Conference `json:"conference"`
- Tracks []Track `json:"tracks"`
- Days []Day `json:"days"`
-}
-
-type Conference struct {
- Title string `json:"title"`
- Venue string `json:"venue"`
- City string `json:"city"`
- Start string `json:"start"`
- End string `json:"end"`
- Days int `json:"days"`
- DayChange string `json:"dayChange"`
- TimeslotDuration string `json:"timeslotDuration"`
- BaseURL string `json:"baseUrl"`
- TimeZoneName string `json:"timeZoneName"`
-}
-
-type Track struct {
- Name string `json:"name"`
-}
-
-type Day struct {
- Date string `json:"date"`
- Start time.Time `json:"start"`
- End time.Time `json:"end"`
- Rooms []Room `json:"rooms"`
-}
-
-type Room struct {
- Name string `json:"name"`
- Events []Event `json:"events"`
-}
-
-type Event struct {
- ID int32 `json:"id"`
- GUID string `json:"guid"`
- Date string `json:"date"`
- Start time.Time `json:"start"`
- End time.Time `json:"end"`
- Duration int32 `json:"duration"`
- Room string `json:"room"`
- URL string `json:"url"`
- Track string `json:"track"`
- Type string `json:"type"`
- Title string `json:"title"`
- Abstract string `json:"abstract"`
- Persons []Person `json:"persons"`
- Attachments []Attachment `json:"attachments"`
- Links []Link `json:"links"`
-}
-
-type Person struct {
- ID int `json:"id"`
- Name string `json:"name"`
-}
-
-type Attachment struct {
- Type string `json:"string"`
- Href string `json:"href"`
- Name string `json:"name"`
-}
-
-type Link struct {
- Href string `json:"href"`
- Name string `json:"name"`
-}
diff --git a/pkg/schedule/parse.go b/pkg/schedule/parse.go
deleted file mode 100644
index b0ed8df..0000000
--- a/pkg/schedule/parse.go
+++ /dev/null
@@ -1,205 +0,0 @@
-package schedule
-
-import (
- "encoding/xml"
- "fmt"
- "time"
-)
-
-type schedule struct {
- XMLName xml.Name `xml:"schedule"`
- Conference conference `xml:"conference"`
- Tracks []track `xml:"tracks>track"`
- Days []day `xml:"day"`
-}
-
-type conference struct {
- Title string `xml:"title"`
- Venue string `xml:"venue"`
- City string `xml:"city"`
- Start string `xml:"start"`
- End string `xml:"end"`
- Days int `xml:"days"`
- DayChange string `xml:"day_change"`
- TimeslotDuration string `xml:"timeslot_duration"`
- BaseURL string `xml:"base_url"`
- TimeZoneName string `xml:"time_zone_name"`
-}
-
-type track struct {
- Name string `xml:",chardata"`
-}
-
-type day struct {
- Date string `xml:"date,attr"`
- Start string `xml:"start,attr"`
- End string `xml:"end,attr"`
- Rooms []room `xml:"room"`
-}
-
-type room struct {
- Name string `xml:"name,attr"`
- Events []event `xml:"event"`
-}
-
-type event struct {
- ID int32 `xml:"id,attr"`
- GUID string `xml:"guid,attr"`
- Date string `xml:"date"`
- Start string `xml:"start"`
- Duration string `xml:"duration"`
- Room string `xml:"room"`
- URL string `xml:"url"`
- Track string `xml:"track"`
- Type string `xml:"type"`
- Title string `xml:"title"`
- Abstract string `xml:"abstract"`
- Persons []person `xml:"persons>person"`
- Attachments []attachment `xml:"attachments>attachment"`
- Links []link `xml:"links>link"`
-}
-
-type person struct {
- ID int `xml:"id,attr"`
- Name string `xml:",chardata"`
-}
-
-type attachment struct {
- Type string `xml:"id,attr"`
- Href string `xml:"href,attr"`
- Name string `xml:",chardata"`
-}
-
-type link struct {
- Href string `xml:"href,attr"`
- Name string `xml:",chardata"`
-}
-
-func (dst *Schedule) Scan(src schedule) error {
- dst.Conference.Scan(src.Conference)
-
- dst.Tracks = make([]Track, len(src.Tracks))
- for i := range src.Tracks {
- dst.Tracks[i].Scan(src.Tracks[i])
- }
- dst.Days = make([]Day, len(src.Days))
- for i := range src.Days {
- if err := dst.Days[i].Scan(src.Days[i]); err != nil {
- return fmt.Errorf("failed to scan day: %w", err)
- }
- }
- return nil
-}
-
-func (dst *Conference) Scan(src conference) {
- dst.Title = src.Title
- dst.Venue = src.Venue
- dst.City = src.City
- dst.Start = src.Start
- dst.End = src.End
- dst.Days = src.Days
- dst.DayChange = src.DayChange
- dst.TimeslotDuration = src.TimeslotDuration
- dst.BaseURL = src.BaseURL
- dst.TimeZoneName = src.TimeZoneName
-}
-
-func (dst *Track) Scan(src track) {
- dst.Name = src.Name
-}
-
-func (dst *Day) Scan(src day) error {
- dst.Date = src.Date
-
- start, err := time.Parse(time.RFC3339, src.Start)
- if err != nil {
- return fmt.Errorf("failed to parse start time: %w", err)
- }
- end, err := time.Parse(time.RFC3339, src.End)
- if err != nil {
- return fmt.Errorf("failed to parse end time: %w", err)
- }
-
- dst.Start = start
- dst.End = end
-
- dst.Rooms = make([]Room, len(src.Rooms))
- for i := range src.Rooms {
- dst.Rooms[i].Scan(src.Rooms[i])
- }
- return nil
-}
-
-func (dst *Room) Scan(src room) {
- dst.Name = src.Name
-
- dst.Events = make([]Event, len(src.Events))
- for i := range src.Events {
- dst.Events[i].Scan(src.Events[i])
- }
-}
-
-func (dst *Event) Scan(src event) error {
- dst.ID = src.ID
- dst.GUID = src.GUID
- dst.Date = src.Date
-
- duration, err := parseDuration(src.Duration)
- if err != nil {
- return err
- }
- start, err := time.Parse(time.RFC3339, src.Date)
- if err != nil {
- start = time.Unix(0, 0)
- }
- dst.Start = start
- dst.End = start.Add(time.Minute * time.Duration(duration))
-
- dst.Room = src.Room
- dst.URL = src.URL
- dst.Track = src.Track
- dst.Type = src.Type
- dst.Title = src.Title
- dst.Abstract = src.Abstract
-
- dst.Persons = make([]Person, len(src.Persons))
- for i := range src.Persons {
- dst.Persons[i].Scan(src.Persons[i])
- }
-
- dst.Attachments = make([]Attachment, len(src.Attachments))
- for i := range src.Attachments {
- dst.Attachments[i].Scan(src.Attachments[i])
- }
-
- dst.Links = make([]Link, len(src.Links))
- for i := range src.Links {
- dst.Links[i].Scan(src.Links[i])
- }
-
- return nil
-}
-
-func (dst *Person) Scan(src person) {
- dst.ID = src.ID
- dst.Name = src.Name
-}
-
-func (dst *Attachment) Scan(src attachment) {
- dst.Type = src.Type
- dst.Href = src.Href
- dst.Name = src.Name
-}
-
-func (dst *Link) Scan(src link) {
- dst.Href = src.Href
- dst.Name = src.Name
-}
-
-func parseDuration(duration string) (int32, error) {
- d, err := time.Parse("15:04", duration)
- if err != nil {
- return 0, err
- }
- return int32(d.Minute() + d.Hour()*60), nil
-}
diff --git a/pkg/schedule/service.go b/pkg/schedule/service.go
deleted file mode 100644
index a73a469..0000000
--- a/pkg/schedule/service.go
+++ /dev/null
@@ -1,116 +0,0 @@
-package schedule
-
-import (
- "bufio"
- "encoding/xml"
- "fmt"
- "net/http"
- "sync"
- "time"
-)
-
-type Service interface {
- GetSchedule() (*Schedule, time.Time, error)
- GetEventByID(id int32) *Event
-}
-
-type service struct {
- pentabarfUrl string
-
- schedule *Schedule
- eventsById map[int32]Event
- lastUpdated time.Time
- accessLock sync.RWMutex
- updateLock sync.Mutex
-}
-
-// TODO: Create a service implementation that persists to DB
-// and isn't in memory
-func NewService(pentabarfUrl string) (Service, error) {
- service := &service{
- pentabarfUrl: pentabarfUrl,
- lastUpdated: time.Unix(0, 0),
- }
-
- err := service.updateSchedule()
- if err != nil {
- return nil, fmt.Errorf("could not read schedule from '%s' (is it a valid pentabarf XML file?): %w", pentabarfUrl, err)
- }
- return service, nil
-}
-
-func (s *service) GetSchedule() (*Schedule, time.Time, error) {
- err := s.updateSchedule()
- if err != nil {
- return nil, time.Time{}, err
- }
-
- s.accessLock.RLock()
- defer s.accessLock.RUnlock()
-
- return s.schedule, s.lastUpdated, nil
-}
-
-func (s *service) GetEventByID(id int32) *Event {
- s.accessLock.RLock()
- defer s.accessLock.RUnlock()
-
- event := s.eventsById[id]
-
- return &event
-}
-
-func (s *service) hasScheduleExpired() bool {
- expire := s.lastUpdated.Add(15 * time.Minute)
- return time.Now().After(expire)
-}
-
-func (s *service) updateSchedule() error {
- if !s.hasScheduleExpired() {
- return nil
- }
-
- if !s.updateLock.TryLock() {
- // don't block if another goroutine is already fetching
- return nil
- }
- defer s.updateLock.Unlock()
-
- res, err := http.Get(s.pentabarfUrl)
- if err != nil {
- return err
- }
-
- reader := bufio.NewReader(res.Body)
-
- var schedule schedule
-
- decoder := xml.NewDecoder(reader)
- if err := decoder.Decode(&schedule); err != nil {
- return fmt.Errorf("failed to decode XML: %w", err)
- }
-
- var newSchedule Schedule
- err = newSchedule.Scan(schedule)
- if err != nil {
- return fmt.Errorf("failed to scan schedule: %w", err)
- }
-
- s.accessLock.Lock()
- defer s.accessLock.Unlock()
-
- s.schedule = &newSchedule
- s.lastUpdated = time.Now()
-
- s.eventsById = make(map[int32]Event)
-
- for _, day := range newSchedule.Days {
- for _, room := range day.Rooms {
- for _, event := range room.Events {
- s.eventsById[event.ID] = event
- }
- }
- }
-
- return nil
-}