commands/list: implement new list command to the search channel
Closes #22
This commit is contained in:
parent
65dfd3136c
commit
529105d340
8 changed files with 198 additions and 17 deletions
|
@ -2,7 +2,7 @@ version: '3'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
sonic:
|
sonic:
|
||||||
image: valeriansaliou/sonic:v1.3.5
|
image: valeriansaliou/sonic:v1.4.0
|
||||||
ports:
|
ports:
|
||||||
- 36999:1491
|
- 36999:1491
|
||||||
volumes:
|
volumes:
|
||||||
|
|
42
flake.lock
42
flake.lock
|
@ -1,5 +1,20 @@
|
||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1659877975,
|
||||||
|
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1662096612,
|
"lastModified": 1662096612,
|
||||||
|
@ -18,22 +33,31 @@
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
"utils": "utils"
|
"sonic-server": "sonic-server"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"utils": {
|
"sonic-server": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": [
|
||||||
|
"flake-utils"
|
||||||
|
],
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1659877975,
|
"lastModified": 1666618211,
|
||||||
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
"narHash": "sha256-kKeIM9dXUi8eYcvSomx8kqSqq9zmqMx4mE5wdpEZ6O8=",
|
||||||
"owner": "numtide",
|
"owner": "pleshevskiy",
|
||||||
"repo": "flake-utils",
|
"repo": "sonic",
|
||||||
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
"rev": "e83de87ebd2e29b210c8cc6e7dfed5d2f14a0d24",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "numtide",
|
"owner": "pleshevskiy",
|
||||||
"repo": "flake-utils",
|
"repo": "sonic",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
19
flake.nix
19
flake.nix
|
@ -1,17 +1,26 @@
|
||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||||
utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
|
||||||
|
sonic-server = {
|
||||||
|
url = "github:pleshevskiy/sonic";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
inputs.flake-utils.follows = "flake-utils";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, nixpkgs, utils }:
|
outputs = inputs @ { self, nixpkgs, flake-utils, ... }:
|
||||||
utils.lib.eachDefaultSystem (system:
|
flake-utils.lib.eachDefaultSystem (system:
|
||||||
let
|
let
|
||||||
pkgs = import nixpkgs { inherit system; };
|
pkgs = import nixpkgs {
|
||||||
|
inherit system;
|
||||||
|
overlays = [ inputs.sonic-server.overlays.default ];
|
||||||
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
devShell = pkgs.mkShell {
|
devShell = pkgs.mkShell {
|
||||||
packages = with pkgs; [ cargo rustc rustfmt clippy rust-analyzer ];
|
packages = with pkgs; [ cargo rustc rustfmt clippy rust-analyzer sonic-server inetutils ];
|
||||||
RUST_SRC_PATH = pkgs.rustPlatform.rustLibSrc;
|
RUST_SRC_PATH = pkgs.rustPlatform.rustLibSrc;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -130,4 +130,35 @@ impl SearchChannel {
|
||||||
req: SuggestRequest,
|
req: SuggestRequest,
|
||||||
);
|
);
|
||||||
);
|
);
|
||||||
|
|
||||||
|
init_command!(
|
||||||
|
/// Enumerates all words in an index.
|
||||||
|
///
|
||||||
|
/// Note: This method requires enabling the `search` feature and start
|
||||||
|
/// connection in Search mode.
|
||||||
|
///
|
||||||
|
/// ```rust,no_run
|
||||||
|
/// # use sonic_channel::*;
|
||||||
|
/// # fn main() -> result::Result<()> {
|
||||||
|
/// let search_channel = SearchChannel::start(
|
||||||
|
/// "localhost:1491",
|
||||||
|
/// "SecretPassword",
|
||||||
|
/// )?;
|
||||||
|
///
|
||||||
|
/// let result = search_channel.list(
|
||||||
|
/// ListRequest::new(Dest::col("search"))
|
||||||
|
/// )?;
|
||||||
|
/// dbg!(result);
|
||||||
|
///
|
||||||
|
/// let result = search_channel.list(
|
||||||
|
/// ListRequest::new(Dest::col("search")).limit(2)
|
||||||
|
/// )?;
|
||||||
|
/// dbg!(result);
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
use ListCommand for fn list(
|
||||||
|
req: ListRequest,
|
||||||
|
);
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@ mod pop;
|
||||||
#[cfg(feature = "ingest")]
|
#[cfg(feature = "ingest")]
|
||||||
mod push;
|
mod push;
|
||||||
|
|
||||||
|
#[cfg(feature = "search")]
|
||||||
|
mod list;
|
||||||
#[cfg(feature = "search")]
|
#[cfg(feature = "search")]
|
||||||
mod query;
|
mod query;
|
||||||
#[cfg(feature = "search")]
|
#[cfg(feature = "search")]
|
||||||
|
@ -29,9 +31,9 @@ pub(crate) use self::{
|
||||||
pub use self::{count::CountRequest, flush::FlushRequest, pop::PopRequest, push::PushRequest};
|
pub use self::{count::CountRequest, flush::FlushRequest, pop::PopRequest, push::PushRequest};
|
||||||
|
|
||||||
#[cfg(feature = "search")]
|
#[cfg(feature = "search")]
|
||||||
pub(crate) use self::{query::QueryCommand, suggest::SuggestCommand};
|
pub(crate) use self::{list::ListCommand, query::QueryCommand, suggest::SuggestCommand};
|
||||||
#[cfg(feature = "search")]
|
#[cfg(feature = "search")]
|
||||||
pub use self::{query::QueryRequest, suggest::SuggestRequest};
|
pub use self::{list::ListRequest, query::QueryRequest, suggest::SuggestRequest};
|
||||||
|
|
||||||
#[cfg(feature = "control")]
|
#[cfg(feature = "control")]
|
||||||
pub(crate) use trigger::TriggerCommand;
|
pub(crate) use trigger::TriggerCommand;
|
||||||
|
|
69
src/commands/list.rs
Normal file
69
src/commands/list.rs
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
use super::StreamCommand;
|
||||||
|
use crate::misc::Dest;
|
||||||
|
use crate::protocol;
|
||||||
|
use crate::result::*;
|
||||||
|
|
||||||
|
/// Parameters for the `suggest` command.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ListRequest {
|
||||||
|
/// Collection and bucket where we should enumerate all words in index.
|
||||||
|
pub dest: Dest,
|
||||||
|
/// Limit of result words.
|
||||||
|
pub limit: Option<usize>,
|
||||||
|
/// Offset of result words.
|
||||||
|
pub offset: Option<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ListRequest {
|
||||||
|
/// Creates a base suggest request.
|
||||||
|
pub fn new(dest: Dest) -> Self {
|
||||||
|
Self {
|
||||||
|
dest,
|
||||||
|
limit: None,
|
||||||
|
offset: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set a limit for the request.
|
||||||
|
pub fn limit(mut self, limit: usize) -> Self {
|
||||||
|
self.limit = Some(limit);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set an offset for the request.
|
||||||
|
pub fn offset(mut self, offset: usize) -> Self {
|
||||||
|
self.offset = Some(offset);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ListCommand {
|
||||||
|
pub(crate) req: ListRequest,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StreamCommand for ListCommand {
|
||||||
|
type Response = Vec<String>;
|
||||||
|
|
||||||
|
fn request(&self) -> protocol::Request {
|
||||||
|
let dest = &self.req.dest;
|
||||||
|
|
||||||
|
protocol::Request::List {
|
||||||
|
collection: dest.collection().clone(),
|
||||||
|
bucket: dest
|
||||||
|
.bucket_opt()
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_else(|| String::from("default")),
|
||||||
|
limit: self.req.limit,
|
||||||
|
offset: self.req.offset,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn receive(&self, res: protocol::Response) -> Result<Self::Response> {
|
||||||
|
if let protocol::Response::Event(protocol::EventKind::List, _id, words) = res {
|
||||||
|
Ok(words)
|
||||||
|
} else {
|
||||||
|
Err(Error::WrongResponse)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -76,6 +76,17 @@ impl Protocol {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
Request::List { collection, bucket, limit, offset } => {
|
||||||
|
write!(res, "LIST {} {}", collection, bucket)?;
|
||||||
|
if let Some(limit) = limit {
|
||||||
|
write!(res, " LIMIT({})", limit)?;
|
||||||
|
}
|
||||||
|
if let Some(offset) = offset {
|
||||||
|
write!(res, " OFFSET({})", offset)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Request::Trigger(triger_req) => match triger_req {
|
Request::Trigger(triger_req) => match triger_req {
|
||||||
TriggerRequest::Consolidate => write!(res, "TRIGGER consolidate")?,
|
TriggerRequest::Consolidate => write!(res, "TRIGGER consolidate")?,
|
||||||
TriggerRequest::Backup(path) => {
|
TriggerRequest::Backup(path) => {
|
||||||
|
@ -123,6 +134,7 @@ impl Protocol {
|
||||||
let event_kind = match segments.next() {
|
let event_kind = match segments.next() {
|
||||||
Some("SUGGEST") => Ok(EventKind::Suggest),
|
Some("SUGGEST") => Ok(EventKind::Suggest),
|
||||||
Some("QUERY") => Ok(EventKind::Query),
|
Some("QUERY") => Ok(EventKind::Query),
|
||||||
|
Some("LIST") => Ok(EventKind::List),
|
||||||
_ => Err(Error::WrongResponse),
|
_ => Err(Error::WrongResponse),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
|
@ -202,6 +214,7 @@ pub struct StartedPayload {
|
||||||
pub enum EventKind {
|
pub enum EventKind {
|
||||||
Suggest,
|
Suggest,
|
||||||
Query,
|
Query,
|
||||||
|
List,
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================//
|
//===========================================================================//
|
||||||
|
@ -223,6 +236,12 @@ pub enum Request {
|
||||||
word: String,
|
word: String,
|
||||||
limit: Option<usize>,
|
limit: Option<usize>,
|
||||||
},
|
},
|
||||||
|
List {
|
||||||
|
collection: String,
|
||||||
|
bucket: String,
|
||||||
|
limit: Option<usize>,
|
||||||
|
offset: Option<usize>,
|
||||||
|
},
|
||||||
Query {
|
Query {
|
||||||
collection: String,
|
collection: String,
|
||||||
bucket: String,
|
bucket: String,
|
||||||
|
|
27
tests/list_command.rs
Normal file
27
tests/list_command.rs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
mod common;
|
||||||
|
use common::*;
|
||||||
|
|
||||||
|
const COLLECTION: &str = "Search";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_list_all_words() {
|
||||||
|
let bucket = "suggest_nearest";
|
||||||
|
let title = "Sweet Teriyaki Beef Skewers";
|
||||||
|
|
||||||
|
let dest = Dest::col_buc(COLLECTION, bucket);
|
||||||
|
|
||||||
|
let ingest_channel = ingest_start();
|
||||||
|
ingest_channel
|
||||||
|
.push(PushRequest::new(dest.clone().obj("1"), title))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
consolidate();
|
||||||
|
|
||||||
|
let search_channel = search_start();
|
||||||
|
match search_channel.list(ListRequest::new(dest.clone())) {
|
||||||
|
Ok(object_ids) => assert_eq!(object_ids, vec!["beef", "skewers", "sweet", "teriyaki"]),
|
||||||
|
Err(e) => unreachable!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
flush_bucket(COLLECTION, bucket);
|
||||||
|
}
|
Loading…
Reference in a new issue