Skip to content
GitLab
Explorer
Connexion
Navigation principale
Rechercher ou aller à…
Projet
lektor
Gestion
Activité
Membres
Labels
Programmation
Tickets
Tableaux des tickets
Jalons
Code
Requêtes de fusion
Dépôt
Branches
Validations
Étiquettes
Graphe du dépôt
Comparer les révisions
Compilation
Pipelines
Jobs
Planifications de pipeline
Artéfacts
Aide
Aide
Support
Documentation de GitLab
Comparer les forfaits GitLab
Forum de la communauté GitLab
Contribuer à GitLab
Donner votre avis
Raccourcis clavier
?
Extraits de code
Groupes
Projets
Afficher davantage de fils d'Ariane
Kubat
lektor
Validations
10b50430
Valider
10b50430
rédigé
Il y a 3 semaines
par
Elliu
Parcourir les fichiers
Options
Téléchargements
Correctifs
Plain Diff
NKDB: make playlists handle use a DKMap
parent
7bedefb9
Branches
Branches contenant la validation
Aucune étiquette associée trouvée
1 requête de fusion
!207
Draft: Add playlist sync
Modifications
2
Afficher les modifications d'espaces
En ligne
Côte à côte
Affichage de
2 fichiers modifiés
lektor_nkdb/src/playlists/mod.rs
+64
-21
64 ajouts, 21 suppressions
lektor_nkdb/src/playlists/mod.rs
lektor_nkdb/src/playlists/playlist.rs
+1
-5
1 ajout, 5 suppressions
lektor_nkdb/src/playlists/playlist.rs
avec
65 ajouts
et
26 suppressions
lektor_nkdb/src/playlists/mod.rs
+
64
−
21
Voir le fichier @
10b50430
...
@@ -2,17 +2,43 @@
...
@@ -2,17 +2,43 @@
pub
(
crate
)
mod
playlist
;
pub
(
crate
)
mod
playlist
;
use
crate
::{
playlists
::
playlist
::
Playlist
,
DatabaseStorage
,
KId
};
use
crate
::{
playlists
::
playlist
::
Playlist
,
DatabaseStorage
,
KId
,
RemoteKId
};
use
anyhow
::{
bail
,
Context
as
_
,
Result
};
use
anyhow
::{
bail
,
Context
as
_
,
Result
};
use
hashbrown
::{
hash_map
,
HashMap
};
use
hashbrown
::
hash_map
;
use
lektor_utils
::
dkmap
::{
DKMap
,
IntoDKMapping
};
use
std
::
sync
::
atomic
::{
AtomicU64
,
Ordering
};
use
std
::
sync
::
atomic
::{
AtomicU64
,
Ordering
};
use
tokio
::
sync
::
RwLock
;
use
tokio
::
sync
::
RwLock
;
type
PlaylistMappingValue
=
(
KId
,
Option
<
RemoteKId
>
,
Playlist
);
type
PlaylistMapping
=
DKMap
<
KId
,
Option
<
RemoteKId
>
,
Playlist
>
;
impl
IntoDKMapping
<
KId
,
Option
<
RemoteKId
>
,
Playlist
>
for
Playlist
{
fn
into_keys_value
(
&
self
)
->
PlaylistMappingValue
{
(
self
.local_id
(),
self
.remote_id
(),
self
.clone
())
}
fn
into_keys
(
&
self
)
->
(
KId
,
Option
<
RemoteKId
>
)
{
(
self
.local_id
(),
self
.remote_id
())
}
fn
into_primary_key
(
&
self
)
->
KId
{
self
.local_id
()
}
fn
into_secondary_key
(
&
self
)
->
Option
<
RemoteKId
>
{
self
.remote_id
()
}
fn
into_value
(
&
self
)
->
Playlist
{
self
.clone
()
}
}
/// This type is just a wrapper around the [PlaylistsContent] with a [RwLock]. For function
/// This type is just a wrapper around the [PlaylistsContent] with a [RwLock]. For function
/// documentation see [PlaylistsContent].
/// documentation see [PlaylistsContent].
#[derive(Debug)]
#[derive(Debug)]
pub
(
crate
)
struct
Playlists
{
pub
(
crate
)
struct
Playlists
{
content
:
RwLock
<
HashMap
<
KId
,
Playlist
>
>
,
content
:
RwLock
<
Playlist
Mapping
>
,
epoch
:
AtomicU64
,
epoch
:
AtomicU64
,
}
}
...
@@ -48,19 +74,19 @@ impl<'a, Storage: DatabaseStorage + Sized> PlaylistsHandle<'a, Storage> {
...
@@ -48,19 +74,19 @@ impl<'a, Storage: DatabaseStorage + Sized> PlaylistsHandle<'a, Storage> {
/// Read a [Playlist].
/// Read a [Playlist].
pub
async
fn
read
<
T
>
(
&
self
,
plt
:
KId
,
cb
:
impl
FnOnce
(
&
Playlist
)
->
T
)
->
Result
<
T
>
{
pub
async
fn
read
<
T
>
(
&
self
,
plt
:
KId
,
cb
:
impl
FnOnce
(
&
Playlist
)
->
T
)
->
Result
<
T
>
{
Ok
(
cb
((
self
.playlists.content
.read
()
.await
)
Ok
(
cb
((
self
.playlists.content
.read
()
.await
)
.get
(
&
plt
)
.get
_k1
(
&
plt
)
.context
(
"playlist not found"
)
?
))
.context
(
"playlist not found"
)
?
))
}
}
/// Get the names and [KId] of the stored [Playlist].
/// Get the names and [KId] of the stored [Playlist].
pub
async
fn
list
(
&
self
)
->
Vec
<
(
KId
,
String
)
>
{
pub
async
fn
list
(
&
self
)
->
Vec
<
(
KId
,
String
)
>
{
(
self
.playlists.content
.read
()
.await
.iter
())
(
self
.playlists.content
.read
()
.await
.iter
())
.map
(|
(
&
id
,
playlist
)
|
(
id
,
playlist
.name
()
.to_string
()))
.map
(|
playlist
|
(
playlist
.local_id
()
,
playlist
.name
()
.to_string
()))
.collect
()
.collect
()
}
}
/// Write a [Playlist]. This will increment the playlists' epoch, even if you do nothing inside
/// Write a [Playlist]. This will increment the playlists' epoch, even if you do nothing inside
/// the callback, prompting all the clients to refre
c
h the playlists.
/// the callback, prompting all the clients to refre
s
h the playlists.
pub
async
fn
write
<
T
>
(
pub
async
fn
write
<
T
>
(
&
self
,
&
self
,
plt
:
KId
,
plt
:
KId
,
...
@@ -68,15 +94,17 @@ impl<'a, Storage: DatabaseStorage + Sized> PlaylistsHandle<'a, Storage> {
...
@@ -68,15 +94,17 @@ impl<'a, Storage: DatabaseStorage + Sized> PlaylistsHandle<'a, Storage> {
admin
:
bool
,
admin
:
bool
,
cb
:
impl
FnOnce
(
&
mut
Playlist
)
->
T
,
cb
:
impl
FnOnce
(
&
mut
Playlist
)
->
T
,
)
->
Result
<
T
>
{
)
->
Result
<
T
>
{
let
mut
this
=
self
.playlists.content
.write
()
.await
;
let
this
=
self
.playlists.content
.write
()
.await
;
let
plt
=
this
let
mut
plt
=
this
.get_
mut
(
&
plt
)
.get_
k1
(
&
plt
)
.context
(
"playlist not found"
)
?
.context
(
"playlist not found"
)
?
.authorize_writes
(
user
,
admin
)
.authorize_writes
(
user
,
admin
)
.context
(
"user not allowed to modify playlist"
)
?
;
.context
(
"user not allowed to modify playlist"
)
?
let
res
=
cb
(
plt
);
.clone
();
self
.storage
.write_playlist
(
plt
)
.await
?
;
let
res
=
cb
(
&
mut
plt
);
self
.storage
.write_playlist
(
&
plt
)
.await
?
;
self
.playlists.epoch
.fetch_add
(
1
,
Ordering
::
AcqRel
);
self
.playlists.epoch
.fetch_add
(
1
,
Ordering
::
AcqRel
);
// TODO: update playlist.updated_at
Ok
(
res
)
Ok
(
res
)
}
}
...
@@ -88,27 +116,42 @@ impl<'a, Storage: DatabaseStorage + Sized> PlaylistsHandle<'a, Storage> {
...
@@ -88,27 +116,42 @@ impl<'a, Storage: DatabaseStorage + Sized> PlaylistsHandle<'a, Storage> {
settings
:
impl
AsyncFnOnce
(
Playlist
)
->
Playlist
,
settings
:
impl
AsyncFnOnce
(
Playlist
)
->
Playlist
,
)
->
Result
<
KId
>
{
)
->
Result
<
KId
>
{
let
mut
this
=
self
.playlists.content
.write
()
.await
;
let
mut
this
=
self
.playlists.content
.write
()
.await
;
let
next_id
=
KId
(
this
.keys
()
.map
(|
KId
(
id
)|
id
+
1
)
.max
()
.unwrap_or
(
1
));
let
next_id
=
KId
(
this
.iter
()
// TODO: maybe add and use a dkmap.keys1() iter (an keys2?)
.map
(|
playlist
|
{
let
KId
(
id
)
=
playlist
.local_id
();
id
+
1
})
.max
()
.unwrap_or
(
1
));
let
plt
=
settings
(
Playlist
::
new
(
next_id
,
name
))
.await
.updated_now
();
let
plt
=
settings
(
Playlist
::
new
(
next_id
,
name
))
.await
.updated_now
();
self
.playlists.epoch
.fetch_add
(
1
,
Ordering
::
AcqRel
);
self
.playlists.epoch
.fetch_add
(
1
,
Ordering
::
AcqRel
);
self
.storage
.write_playlist
(
&
plt
)
.await
?
;
self
.storage
.write_playlist
(
&
plt
)
.await
?
;
this
.insert
(
next_id
,
plt
);
this
.insert_only
(
plt
)
.context
(
"cannot create playlist: a playlist with this same KId already exists"
)
?
;
Ok
(
next_id
)
Ok
(
next_id
)
}
}
/// Delete a [Playlist].
/// Delete a [Playlist].
pub
async
fn
delete
(
&
self
,
plt
:
KId
,
user
:
impl
AsRef
<
str
>
,
admin
:
bool
)
->
Result
<
()
>
{
pub
async
fn
delete
(
&
self
,
plt
:
KId
,
user
:
impl
AsRef
<
str
>
,
admin
:
bool
)
->
Result
<
()
>
{
match
self
.playlists.content
.write
()
.await
.entry
(
plt
)
{
let
mut
playlists
=
self
.playlists.content
.write
()
.await
;
hash_map
::
Entry
::
Vacant
(
_
)
=>
bail!
(
"playlist not found"
),
match
playlists
.get_k1
(
&
plt
)
{
hash_map
::
Entry
::
Occupied
(
mut
entry
)
=>
{
Some
(
playlist
)
=>
{
(
entry
.get_mut
())
playlist
.authorize_writes
(
user
,
admin
)
.authorize_writes
(
user
,
admin
)
.context
(
"user not allowed to modify the playlist"
)
?
;
.context
(
"user not allowed to modify the playlist"
)
?
;
entry
.remove
();
if
let
Err
(
err
)
=
playlists
.delete_k1
(
&
plt
)
{
log
::
error!
(
"failed to delete playlist '{plt}' from memory: {err}"
)
}
if
let
Err
(
err
)
=
self
.storage
.delete_playlist
(
plt
)
.await
{
if
let
Err
(
err
)
=
self
.storage
.delete_playlist
(
plt
)
.await
{
log
::
error!
(
"failed to delete playlist '{plt}': {err}"
)
log
::
error!
(
"failed to delete playlist '{plt}'
from disk
: {err}"
)
}
}
}
}
None
=>
bail!
(
"playlist not found"
),
}
}
Ok
(())
Ok
(())
}
}
...
@@ -118,7 +161,7 @@ impl Playlists {
...
@@ -118,7 +161,7 @@ impl Playlists {
/// Create a new [Playlists] store, initialized by an initial list of [Playlist].
/// Create a new [Playlists] store, initialized by an initial list of [Playlist].
pub
(
crate
)
fn
new
(
iter
:
impl
IntoIterator
<
Item
=
Playlist
>
)
->
Self
{
pub
(
crate
)
fn
new
(
iter
:
impl
IntoIterator
<
Item
=
Playlist
>
)
->
Self
{
Self
{
Self
{
content
:
RwLock
::
new
(
iter
.into_iter
()
.map
(|
plt
|
(
plt
.local_id
(),
plt
))
.collect
(
)),
content
:
RwLock
::
new
(
DKMap
::
from_iter
(
iter
.into_iter
()
)),
epoch
:
AtomicU64
::
new
(
0
),
epoch
:
AtomicU64
::
new
(
0
),
}
}
}
}
...
...
Ce diff est replié.
Cliquez pour l'agrandir.
lektor_nkdb/src/playlists/playlist.rs
+
1
−
5
Voir le fichier @
10b50430
...
@@ -143,11 +143,7 @@ impl Playlist {
...
@@ -143,11 +143,7 @@ impl Playlist {
/// Tells if someone is authorized to modify the playlist. It can be in the [Self::owners]
/// Tells if someone is authorized to modify the playlist. It can be in the [Self::owners]
/// list, or be an admin.
/// list, or be an admin.
pub
(
crate
)
fn
authorize_writes
(
pub
(
crate
)
fn
authorize_writes
(
&
self
,
user
:
impl
AsRef
<
str
>
,
admin
:
bool
)
->
Option
<&
Self
>
{
&
mut
self
,
user
:
impl
AsRef
<
str
>
,
admin
:
bool
,
)
->
Option
<&
mut
Self
>
{
(
admin
||
(
self
.owners
.iter
())
.any
(|
owner
|
owner
.as_ref
()
==
user
.as_ref
()))
.then_some
(
self
)
(
admin
||
(
self
.owners
.iter
())
.any
(|
owner
|
owner
.as_ref
()
==
user
.as_ref
()))
.then_some
(
self
)
}
}
...
...
Ce diff est replié.
Cliquez pour l'agrandir.
Aperçu
0%
Chargement en cours
Veuillez réessayer
ou
joindre un nouveau fichier
.
Annuler
You are about to add
0
people
to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Enregistrer le commentaire
Annuler
Veuillez vous
inscrire
ou vous
se connecter
pour commenter