@@ -55,6 +55,7 @@ defmodule Mongo do
55
55
alias Mongo.Topology
56
56
alias Mongo.UrlParser
57
57
alias Mongo.Session.ServerSession
58
+ alias Mongo.Session
58
59
59
60
@ timeout 15000 # 5000
60
61
@@ -292,12 +293,21 @@ defmodule Mongo do
292
293
293
294
opts = Keyword . drop ( opts , ~w( bypass_document_validation max_time projection return_document sort upsert collation) a )
294
295
295
- with { :ok , _conn , doc } <- issue_command ( topology_pid , cmd , :write , opts ) do
296
+ with { :ok , doc } <- issue_command ( topology_pid , cmd , :write , opts ) do
296
297
{ :ok , doc [ "value" ] }
297
298
end
298
299
299
300
end
300
301
302
+ def start_session ( topology_pid , type , opts ) do
303
+ with { :ok , session , _ , _ } <- Topology . checkout_session ( topology_pid , type , :explicit , opts ) do
304
+ { :ok , session }
305
+ else
306
+ { :new_connection , _server } ->
307
+ start_session ( topology_pid , type , opts )
308
+ end
309
+ end
310
+
301
311
@ doc """
302
312
This function is very fundamental. First a server is selected. If no explicit session id is found, then
303
313
the Topology-Module returns an implicit session id. The `opts` is updated for using the new session id.
@@ -308,43 +318,27 @@ defmodule Mongo do
308
318
309
319
Logger . debug ( "issue_command: write #{ inspect cmd } " )
310
320
311
- with { :ok , conn , _ , _ , session_id } <- Topology . select_server ( topology_pid , :write , opts ) ,
312
- { :ok , doc } <- exec_command ( conn , update_session_id ( cmd , session_id ) , opts ) ,
313
- :ok <- checkin_session_id ( topology_pid , cmd , session_id ) do
314
- { :ok , conn , doc }
321
+ with { :ok , session , slave_ok , _mongos } <- Topology . checkout_session ( topology_pid , :write , :implicit , opts ) ,
322
+ { :ok , doc } <- exec_command_session ( session , cmd , opts ) ,
323
+ :ok <- Topology . checkin_session ( topology_pid , session ) do
324
+ { :ok , doc }
315
325
else
316
- { :new_connection , _server } ->
317
- issue_command ( topology_pid , cmd , :write , opts )
326
+ { :new_connection , _server } -> issue_command ( topology_pid , cmd , :write , opts )
318
327
end
319
328
end
320
329
def issue_command ( topology_pid , cmd , :read , opts ) do
321
330
322
331
Logger . debug ( "issue_command: read #{ inspect cmd } " )
323
- with { :ok , conn , slave_ok , _ , session_id } <- Topology . select_server ( topology_pid , :read , opts ) ,
332
+ with { :ok , session , slave_ok , _mongos } <- Topology . checkout_session ( topology_pid , :read , :implict , opts ) ,
324
333
opts = Keyword . put ( opts , :slave_ok , slave_ok ) ,
325
- { :ok , doc } <- exec_command ( conn , update_session_id ( cmd , session_id ) , opts ) ,
326
- :ok <- checkin_session_id ( topology_pid , cmd , session_id ) do
327
- { :ok , conn , doc }
334
+ { :ok , doc } <- exec_command_session ( session , cmd , opts ) ,
335
+ :ok <- Topology . checkin_session ( topology_pid , session ) do
336
+ { :ok , doc }
328
337
else
329
- { :new_connection , _server } ->
330
- issue_command ( topology_pid , cmd , :read , opts )
338
+ { :new_connection , _server } -> issue_command ( topology_pid , cmd , :read , opts )
331
339
end
332
340
end
333
341
334
- defp update_session_id ( cmd , nil ) do
335
- cmd
336
- end
337
- defp update_session_id ( cmd , % ServerSession { :session_id => session_id } ) do
338
- Logger . debug ( "update_session_id for cmd #{ inspect session_id } " )
339
- Keyword . merge ( cmd , [ lsid: % { id: session_id } ] )
340
- end
341
- defp checkin_session_id ( _topology_pid , _cmd , nil ) , do: :ok
342
- defp checkin_session_id ( topology_pid , cmd , session_id ) do
343
- case Keyword . get ( cmd , :lsid , :implicit ) do
344
- :implicit -> Topology . checkin_session_id ( topology_pid , session_id )
345
- _ -> :ok
346
- end
347
- end
348
342
349
343
@ doc """
350
344
Finds a document and replaces it.
@@ -383,7 +377,7 @@ defmodule Mongo do
383
377
384
378
opts = Keyword . drop ( opts , ~w( bypass_document_validation max_time projection return_document sort upsert collation) a )
385
379
386
- with { :ok , _conn , doc } <- issue_command ( topology_pid , cmd , :write , opts ) , do: { :ok , doc [ "value" ] }
380
+ with { :ok , doc } <- issue_command ( topology_pid , cmd , :write , opts ) , do: { :ok , doc [ "value" ] }
387
381
end
388
382
389
383
defp should_return_new ( :after ) , do: true
@@ -414,7 +408,7 @@ defmodule Mongo do
414
408
] |> filter_nils ( )
415
409
opts = Keyword . drop ( opts , ~w( max_time projection sort collation) a )
416
410
417
- with { :ok , _conn , doc } <- issue_command ( topology_pid , cmd , :write , opts ) , do: { :ok , doc [ "value" ] }
411
+ with { :ok , doc } <- issue_command ( topology_pid , cmd , :write , opts ) , do: { :ok , doc [ "value" ] }
418
412
end
419
413
420
414
@ doc false
@@ -518,7 +512,7 @@ defmodule Mongo do
518
512
519
513
opts = Keyword . drop ( opts , ~w( max_time) a )
520
514
521
- with { :ok , _conn , doc } <- issue_command ( topology_pid , cmd , :read , opts ) , do: { :ok , doc [ "values" ] }
515
+ with { :ok , doc } <- issue_command ( topology_pid , cmd , :read , opts ) , do: { :ok , doc [ "values" ] }
522
516
end
523
517
524
518
@ doc """
@@ -594,13 +588,13 @@ defmodule Mongo do
594
588
Mongo.find_one(top, "jobs", %{}, read_concern: %{level: "local"})
595
589
"""
596
590
@ spec find_one ( GenServer . server , collection , BSON . document , Keyword . t ) :: BSON . document | nil
597
- def find_one ( conn , coll , filter , opts \\ [ ] ) do
591
+ def find_one ( topology_pid , coll , filter , opts \\ [ ] ) do
598
592
opts = opts
599
593
|> Keyword . delete ( :sort )
600
594
|> Keyword . put ( :limit , 1 )
601
595
|> Keyword . put ( :batch_size , 1 )
602
596
603
- conn
597
+ topology_pid
604
598
|> find ( coll , filter , opts )
605
599
|> Enum . at ( 0 )
606
600
end
@@ -614,22 +608,40 @@ defmodule Mongo do
614
608
def command ( topology_pid , cmd , opts \\ [ ] ) do
615
609
rp = ReadPreference . defaults ( % { mode: :primary } )
616
610
rp_opts = [ read_preference: Keyword . get ( opts , :read_preference , rp ) ]
617
- with { :ok , _conn , doc } <- Mongo . issue_command ( topology_pid , cmd , :read , rp_opts ) do
611
+ with { :ok , doc } <- Mongo . issue_command ( topology_pid , cmd , :read , rp_opts ) do
618
612
{ :ok , doc }
619
613
end
620
614
end
621
615
616
+ @ doc false
617
+ @ spec exec_command_session ( pid , BSON . document , Keyword . t ) :: { :ok , BSON . document | nil } | { :error , Mongo.Error . t }
618
+ def exec_command_session ( session , cmd , opts ) do
619
+
620
+ Logger . debug ( "Executing cmd: #{ inspect cmd } " )
621
+
622
+ action = % Query { action: :command }
623
+
624
+ with { :ok , conn , cmd } <- Session . bind_session ( session , cmd ) ,
625
+ { :ok , _cmd , doc } <- DBConnection . execute ( conn , action , [ cmd ] , defaults ( opts ) ) ,
626
+ { :ok , doc } <- check_for_error ( doc ) do
627
+ { :ok , doc }
628
+ end
629
+
630
+ end
631
+
622
632
@ doc false
623
633
@ spec exec_command ( pid , BSON . document , Keyword . t ) :: { :ok , BSON . document | nil } | { :error , Mongo.Error . t }
624
634
def exec_command ( conn , cmd , opts ) do
625
- action = % Query { action: :command }
626
635
627
636
Logger . debug ( "Executing cmd: #{ inspect cmd } " )
628
637
638
+ action = % Query { action: :command }
639
+
629
640
with { :ok , _cmd , doc } <- DBConnection . execute ( conn , action , [ cmd ] , defaults ( opts ) ) ,
630
641
{ :ok , doc } <- check_for_error ( doc ) do
631
642
{ :ok , doc }
632
643
end
644
+
633
645
end
634
646
635
647
defp check_for_error ( % { "ok" => ok } = response ) when ok == 1 , do: { :ok , response }
@@ -682,6 +694,13 @@ defmodule Mongo do
682
694
## Examples
683
695
684
696
Mongo.insert_one(pid, "users", %{first_name: "John", last_name: "Smith"})
697
+
698
+ {:ok, session} = Mongo.start_session(pid)
699
+ Session.start_transaction(session)
700
+ Mongo.insert_one(pid, "users", %{first_name: "John", last_name: "Smith"}, session: session)
701
+ Session.commit_transaction(session)
702
+ Mongo.end_sessions([pid])
703
+
685
704
"""
686
705
@ spec insert_one ( GenServer . server , collection , BSON . document , Keyword . t ) :: result ( Mongo.InsertOneResult . t )
687
706
def insert_one ( topology_pid , coll , doc , opts \\ [ ] ) do
@@ -698,12 +717,11 @@ defmodule Mongo do
698
717
insert: coll ,
699
718
documents: [ doc ] ,
700
719
ordered: Keyword . get ( opts , :ordered ) ,
701
- writeConcern: write_concern ,
702
- bypassDocumentValidation: Keyword . get ( opts , :bypass_document_validation ) ,
703
- lsid: Keyword . get ( opts , :lsid , :implicit )
720
+ writeConcern: write_concern , ## todo in der Transaction löschen
721
+ bypassDocumentValidation: Keyword . get ( opts , :bypass_document_validation )
704
722
] |> filter_nils ( )
705
723
706
- with { :ok , _conn , doc } <- Mongo . issue_command ( topology_pid , cmd , :write , opts ) do
724
+ with { :ok , doc } <- Mongo . issue_command ( topology_pid , cmd , :write , opts ) do
707
725
case doc do
708
726
% { "writeErrors" => _ } -> { :error , % Mongo.WriteError { n: doc [ "n" ] , ok: doc [ "ok" ] , write_errors: doc [ "writeErrors" ] } }
709
727
_ ->
@@ -757,7 +775,7 @@ defmodule Mongo do
757
775
lsid: Keyword . get ( opts , :lsid )
758
776
] |> filter_nils ( )
759
777
760
- with { :ok , _conn , doc } <- issue_command ( topology_pid , cmd , :write , opts ) do
778
+ with { :ok , doc } <- issue_command ( topology_pid , cmd , :write , opts ) do
761
779
case doc do
762
780
% { "writeErrors" => _ } -> { :error , % Mongo.WriteError { n: doc [ "n" ] , ok: doc [ "ok" ] , write_errors: doc [ "writeErrors" ] } }
763
781
_ ->
@@ -828,7 +846,7 @@ defmodule Mongo do
828
846
lsid: Keyword . get ( opts , :lsid )
829
847
] |> filter_nils ( )
830
848
831
- with { :ok , _conn , doc } <- issue_command ( topology_pid , cmd , :write , opts ) do
849
+ with { :ok , doc } <- issue_command ( topology_pid , cmd , :write , opts ) do
832
850
case doc do
833
851
% { "writeErrors" => _ } -> { :error , % Mongo.WriteError { n: doc [ "n" ] , ok: doc [ "ok" ] , write_errors: doc [ "writeErrors" ] } }
834
852
% { "ok" => _ok , "n" => n } ->
@@ -949,7 +967,7 @@ defmodule Mongo do
949
967
] |> filter_nils ( )
950
968
951
969
952
- with { :ok , _conn , doc } <- issue_command ( topology_pid , cmd , :write , opts ) do
970
+ with { :ok , doc } <- issue_command ( topology_pid , cmd , :write , opts ) do
953
971
954
972
case doc do
955
973
@@ -973,13 +991,6 @@ defmodule Mongo do
973
991
end
974
992
end
975
993
976
- def start_session ( top ) do
977
- ## todo error code handling
978
- with { :ok , % { "id" => uuid , "ok" => ok } } when ok == 1 <- command ( top , [ startSession: 1 ] , database: "admin" ) do
979
- uuid
980
- end
981
- end
982
-
983
994
def end_sessions ( top , sessions ) do
984
995
## todo error code handling
985
996
with { :ok , % { "ok" => ok } } when ok == 1 <- command ( top , [ endSessions: sessions ] , database: "admin" ) do
0 commit comments