Come automatizzare la generazione di ID?

1

Sto lavorando su yesod che ha percorsi come

/make/something MakeR POST

su quale server genera un oggetto e restituisce il suo ID racchiuso in JSON. Io uso Int come ID.

Quindi, ho finito per utilizzare un tipo di dati come questo

data Manager
  = Manager
  { objects :: IntMap Object
  , nextId  :: Int
  }

Li memorizzo in TVar in App . E ogni volta che viene chiamato il gestore per MakeR , incremento% il campo nextId di Manager .

Il problema è che ho molti manager come sopra e voglio astrarre l'incremento del contatore ID.

Un'idea sarebbe quella di usare una monade di stato. Ma, ancora, devo tenere banco da qualche parte. In questo modo non si sente il suono:

data App = App
  { ...
  , appAMap :: TVar (IntMap A)
  , appACtr :: TVar Int
  , appBMap :: TVar (IntMap B)
  , appBCtr :: TVar Int
    ...
  }

Esiste uno schema o un approccio che posso utilizzare per automatizzare la generazione di ID senza perdere la solidità?

    
posta wowofbob 08.06.2017 - 15:24
fonte

1 risposta

3

La generazione dell'ID è stateful.

In genere vedo due approcci alla generazione di ID. È possibile generare un ID a caso in un modo molto improbabile di collidere (ad esempio UUID casuale come suggerito da @Ewan) o delegare a un'origine dati ACID per generare un ID. Ad esempio potresti usare una tabella PostgreSQL per generare un ID autoincrementante per te. Puoi archiviare il tuo ID in memoria come fai, ma causerà collisioni quando riavvii l'app o se sono in esecuzione più istanze dell'app.

Puoi astrarre la generazione di ID creando un'interfaccia polimorfa sul tipo di id. Non conosco Haskell, ma in Scala sarebbe qualcosa di simile (usando una Monade per catturare l'effetto collaterale della creazione di un ID):

trait IdGenerator[M[_], ID] {
  val generateId: M[ID]
}

class UuidIdGenerator extends IdGenerator[Task, UUID] {
  override val generateId = Task.delay(UUID.randomUUD())
}

// Thread-safe id generation for a single instance
class InMemoryIdGenerator extends IdGenerator[Task, Int] {
  private val id = new AtomicInteger(0)
  override val generateId = Task.delay(id.incrementAndGet())
}
    
risposta data 09.06.2017 - 00:23
fonte

Leggi altre domande sui tag